Author Topic: (Yet Another) DIY Multislope ADC  (Read 13272 times)

0 Members and 2 Guests are viewing this topic.

Offline Kleinstein

  • Super Contributor
  • ***
  • Posts: 14219
  • Country: de
Re: (Yet Another) DIY Multislope ADC
« Reply #50 on: April 17, 2024, 07:08:49 am »
The Si570 is made for low jitter and this comes at the cost of quite high power consumption. The µC internal PLL is more build for low power and this comes with more jitter. The question is just how much.
With a modulation in the 100-300 kHz range the jitter level to worry about is if one gets better than a few ps RMS for a frequency offset of some 200-600 kHz. AFAIK 74AC gates and likely the 74LV4053 switches have RMS jitter of some 1 ps.  The target specs for the clock are better than some -110 dBc for a 100 kHz offset. Most oscillators are OK with this.  No need for a special grade oscillator.
For the supply good decoupling can be needed for the oscillator - not sure of the solution on the RP2040 board is good enough


If the jitter of the µC is an issue one could still consider the external synchronization like it is done with most DMMs (e.g. 34401, 3458, K200x). This needs an external flipflop, like 74AC74 or similar. If the RP2040 is still running with the PLL, the  PIO software would also need some synchronization part to get a correct setup time / phase relative to the master clock.
The external sync would also avoid issues from the µC internal operation effecting output delays or the PLL, that can effect the INL. Though small, I have seen such an effect with an AVR.
So there can be another reason to use external synchronization, not just jitter.
 

Offline iMo

  • Super Contributor
  • ***
  • Posts: 4795
  • Country: pm
  • It's important to try new things..
Re: (Yet Another) DIY Multislope ADC
« Reply #51 on: April 17, 2024, 07:25:30 am »
And what about the 50/60Hz mains? Do we need the sync there as well? Most dmms have it.

Quote
If the RP2040 is still running with the PLL, the  PIO software would also need some synchronization part to get a correct setup time / phase relative to the master clock.

The PIO runs from a "clock" derived off the pll, but the MCU works fully async of the PIO as the data transfer PIO<->MCU gets via I/O FIFOs, there is no direct interaction between the PIO SM and the MCU (or anything else, the residual ADC is r/w async via FIFO too) at the "particular hw signal level" during a MS cycle (MS cycle being the "runup PWM modulation" as you call it), afaik. So the PIO SM clock "is" the master clock, imho.

The only critical interaction as of today is when the MCU requests the PIO SM to "make a single XXX PLC long measurement" with a single MS cycle in it (with the pre- and post- residual ADC readings), that request is not synced to anything today (the SW on the github is just a MS3 cycle testing stuff, not a working DMM) and most probably subject to a large sw/system jitter (as it works with interrupts/DMA/FIFOs/USB_printf in a free while() loop).

PS: that could be done easily by calling the MScycle request in an interrupt, where the interrupt will be triggered by an external edge ("the sampling rate" generated by the MCU), and within the interrupt the 4 data received from the MScycle will be written into a sw FIFO. The FIFO data could be then read by the main loop. There will be a jitter in that sampling period, like sub usecond, I would guess.
« Last Edit: April 17, 2024, 09:54:20 am by iMo »
 

Offline Kleinstein

  • Super Contributor
  • ***
  • Posts: 14219
  • Country: de
Re: (Yet Another) DIY Multislope ADC
« Reply #52 on: April 17, 2024, 09:54:00 am »
In most case one can get away without the ADC synchoronized to mains. As the integration times is than a mulitiple of mains periods one would have to wait nearly a full period after the short rundown. This makes a full sync here not that attractive. It could still be nice to have the option to synchronize the start of the conversion to some trigger signal - not just mains.

Running a PLL to have the clock direct linked to mains, as done in a few meters (e.g. Prema, Solartron) would make it hard to get low jitter. So many other don't use this. The alternative may be using a fixed crystal clock and if really needed adjust the number of clock cycles in a conversion to follow main frequency variations. It needs some extra math to handle the result than.

Using the PIO clock as the master clock may or may not work. If there is too much jitter or delay/frequency modulation (e.g. via supply or internal states or other io pins) one may have to use external syncronization and than an external master clock. That clock would than also feed the PLL. The PIO clock would be a multiple of the master clcok and would need some extra SW to synchronize to the master clock at least somewhat. Otherwise there could a the risk to no get a proper setup time for the sync flip flops.

The alternative may be to run the whole system without PLL, e.g. from a 16 MHz clock. The µC may still be fast enough.  No PLL is the way I run my STM32L051 based version.
 

Offline iMo

  • Super Contributor
  • ***
  • Posts: 4795
  • Country: pm
  • It's important to try new things..
Re: (Yet Another) DIY Multislope ADC
« Reply #53 on: April 17, 2024, 10:08:49 am »
Now, let us start simple. Let us assume (for a while) the PIO's clock is "perfect".
An MCU interrupt triggered by the MCU's PWM output (the set period of the "DMM's sampling rate", like 4x per second) requests PIO to provide a single 10PLC measurement, and the PIO performs the requested measurement (== preADC, MScycle 200ms long, postADC), then the PIO returns the preADC, PWMA/PWMB count and postADC values, those values are read by the MCU afterwards.
There will be no jitter within PIO's MScycle, but there will be a "small" jitter (say sub usec) in the sampling period (because it is triggered via the interrupt).
How that jitter in the sampling period influences a typical measurement?
PS: outside the single "10PLC measurment" the PIO performs "dithering" as it is done today.
PS1: there is a jitter in the start of the preADC and the postADC as those are triggered by interrupts as well..
PS2: "MScycle" means the runup charge balancing sequence..
« Last Edit: April 17, 2024, 11:09:27 am by iMo »
 

Offline Kleinstein

  • Super Contributor
  • ***
  • Posts: 14219
  • Country: de
Re: (Yet Another) DIY Multislope ADC
« Reply #54 on: April 17, 2024, 10:45:04 am »
Any jitter with the auxiliary ADC should not be that bad, if this is in hold phases of the integrator. The drift should be rather low (e.g. a few LSB per ms).
In most applications a slight jitter in when the conversion actually starts is also not that bad. After all the conversions are usually integrating over quite some time (e.g. 16 ms and up).
The actual integration time should still be accurate to the clock cylce. In many cases just a preset number of modulation cycles. A vaiation there would change the gain.
 

Offline iMo

  • Super Contributor
  • ***
  • Posts: 4795
  • Country: pm
  • It's important to try new things..
Re: (Yet Another) DIY Multislope ADC
« Reply #55 on: April 17, 2024, 10:54:20 am »
As of today the preADC and postADC samplings are below XX usecs before/after MScycle (incl interrupt jitter, the XX depends on the ADC SPI clock) while the integrator is on hold.. (see above my scope shot at 2MHz SPI clock aprox 12us pre- and 5us post-)..

So the moral of the story here is - everything in this design will be jittery/async, except the "MScycle runup charge balancing sequence".. :D
« Last Edit: April 17, 2024, 11:16:38 am by iMo »
 

Offline diminddl

  • Newbie
  • Posts: 2
  • Country: ua
    • Dmytro Engineering
Re: (Yet Another) DIY Multislope ADC
« Reply #56 on: April 17, 2024, 10:05:04 pm »
Ok, I see..
What I do not understand fully (a 2040 beginner here..) is following:
Quote
    // IRQ setup:
    // PIO sends interrupt in IRQ0 for first residue reading
    // IRQ0 handler starts DMA to read SPI of the ADC
    // when DMA finishes, it sends a value over to the TX FIFO of the PIO instance
    // all this time an OUT command was stalling the state machine to wait for the reading to finish
Why do you send the ADC value to the TX FIFO of the PIO instance?
That delays the MAES rising edge by XXus when the integrator's input voltage has been already disconnected (so it may change during the "XXus long" preADC conversion)..
What I thought above is to have the ADC channel "independent" of the PIO instance (so both will do in parallel, no need to stall the SM..). Something like that..

PS: below what I see now.. preADC samples some 12uS before MAES=1 and postADC about 4-5us after MAES=0 (with 2MHz spi).

Hello, I am the one who wrote the software for this thing, and I would like to clear up some things.

First of all, the code was essentially frozen mid development (at least for me, according to my last commit to the repo) 2 years ago. So forgive me if I won't explain exactly why some stuff was done the way it was.

Also, I was (just like you) still learning to use the RP2040, PIO and it's SDK at that point, so some things are far from optimal. I mention some of them in the hackaday write-up mentioned earlier (that was written after an extra year of experience with the platform).

Quote
Why do you send the ADC value to the TX FIFO of the PIO instance?
The answer is we don't. If you look at the code it actually puts in just a 1.
Code: [Select]
pio_sm_put(pio, multislopeSM, (uint32_t)1); And if you look at the PIO code and the attached comment:
Code: [Select]
out NULL, 32        side 0              ; stall until DMA finished reading the ADC
This was just a crude way of stalling the state machine and letting the reside ADC read out the residue. This operation indeed is a bit jittery (because we are relying on the CPU to react to the interrupt, set everything up and trigger the reading), but as it was explained to me at the time, as long as all the switches are off, meaning they are not injecting any charge into the integrator, then the absolute time that the residue reading happens doesn't really matter (within reason).

The plan was to optimize the PIO code enough to be able to include a crude SPI readout block in a different state machine within the same PIO instance, this would allow us to use the inter state machine interrupts with a predictable 1 cycle delay to fire the readout of the reside ADC. But me and NNNI both got busy at the same time so we never got around to fully implementing that.

If you have any other questions about the PIO, or the RP2040 in general, fell free to do so, I will try my best to answer them.
 
The following users thanked this post: iMo

Online PCB.Wiz

  • Super Contributor
  • ***
  • Posts: 1555
  • Country: au
Re: (Yet Another) DIY Multislope ADC
« Reply #57 on: April 18, 2024, 06:20:05 am »
The alternative may be to run the whole system without PLL, e.g. from a 16 MHz clock. The µC may still be fast enough.  No PLL is the way I run my STM32L051 based version.
Having that option would certainly allow easy A-B comparison testing.
I listed a couple of Abracon TXCO's above that come in 12MHz, and I've found some very low phase noise oscillators for Audio from NDK, impressive for a 2520 case.

Ultra low phase jitter:Typ. 43fs  Phase noise Typ : -115dBc @ 10Hz, -164 dBc @ 1 kHz offset frequency.

Digikey has these in codes NSC5083D-24.576M, NSC5083D-45.158M, NSC5083D-49.152M  at $2.80/1

To use those, you could feed OSCOUT via a resistor to the XIN pin, boot with the OSC tri-stated (so 12MHz) and then use a GPIO pin to enable the new master clock once ready.

NDK do quote 24MHz and 48MHz as possible order codes, likely with some MOQ. 22.5792 MHz is the lowest valid freq, the 2520 package likely cannot fit lower xtals.

I've not used a RP2040 PLL, but at 24.576MHz I think there is a viable 48MHz USB solution with a ~381ppm offset, with *41/(3*7)  VCO = 1007.616
Another solution may exist for 45.158MHz   45.158*17 = 767.686/(4*4) = 47.980375  ~409ppm

External D-FF could be clocked from this master clock, if needed.

 
The following users thanked this post: iMo

Offline iMo

  • Super Contributor
  • ***
  • Posts: 4795
  • Country: pm
  • It's important to try new things..
Re: (Yet Another) DIY Multislope ADC
« Reply #58 on: April 18, 2024, 06:48:50 am »
@diminddl: Hi, thanks for the clarification! Yep, I like the design because of its simplicity. Of course, messing with the 2040 and its PIO requires some lead in..  ::)

I've been playing with the sw part only at this stage - the C source - and slowly getting the grip.. :)

I made small cleanups here and there (mostly to make it easier to read and save a couple of bits), added the PWM_Sampling_rate signal generation with an interrupt which sets a flag at each sampling period start such I can sync the start of the xPLC measurement and it works fine.

Also I investigated the issue NNNI indicated in past with the wrong sequence of the auxADC readings, and after my cleanup of the flag handling it still works. As a proof I've been changing the auxADC input voltage (with help of the MAES signal) such I can see which is pre- and which post- auxADC reading, and it works fine, it seems.

Code: [Select]
void pio_irq(){

    gpio_put(CS, false);
    irq_set_enabled(DMA_IRQ_0, true);
    dma_start_channel_mask((1u << dma_tx) | (1u << dma_rx));

    if (pio0_hw->irq & 1) {
        // PIO0 IRQ0 fired means we need to take first MCP reading
        // start DMAs simultaneously
        // enable IRQ
        firstAuxADCreading = true;
        pio0_hw->irq = 1;
   
    }else if (pio0_hw->irq & 2) {
        // PIO0 IRQ1 fired means it's time for the second reading
        firstAuxADCreading = false;
        pio0_hw->irq = 2;
    }   
}

// MSADC SAMPLING period
void my_PLC_PERIOD_isr()    //  fired by the PWM at PIN0 (example), max Speriod 120ms @96MHz CPU clock
{
        MeasurePLC = true;
        pwm_clear_irq(pwm_gpio_to_slice_num(PINpwm)); //Clear the interrupt flag
}

The stuff with the DMAing auxADC and PIO does not need to be modified at this stage as the 10-20us lost with the stalling the SM plays no significant role there, as has been discussed above.

Also the jittery coming from the interrupts/FIFOs etc. will most probably not have significant influence provided the MScycle charge balancing sequence itself is rock stable (the part where MAES=1), so far let say it is stable (unless there is a larger pll jitter, that needs to be investigated).

One thing is the "configureDMA();" at the end of the DMA interrupt handler routine.. Can we somehow re-arm the DMA without calling the huge "complete DMA config"? I've tried my best but I was not successful so far.

PS: note the math with the reading the auxADC SPI data below is for my MAX1247 ADC..

Code: [Select]
void dma_irq_handler() {
    // Clear interrupt.
    // and disable the interrupt
    dma_hw->ints0 = (1u << dma_rx);
    irq_set_enabled(DMA_IRQ_0, false);
    gpio_put(CS, true);
    uint16_t auxADCreading = ((DMA_SPI_ADC_readBuffer[1] << 8) | (DMA_SPI_ADC_readBuffer[2])) >> 3;

    if(firstAuxADCreading) {
        auxADCresultPreMultislope =   auxADCreading;
    } else {
        auxADCresultPostMultislope  =  auxADCreading;
    }

    pio_sm_put(pio, multislopeSM, (uint32_t)1);
    configureDMA();    // HOW TO GET RID OF THIS CHUNK??? :)
}

With the synced measurement in the main - example only, still not a working DMM :)

Code: [Select]
..
    // Start running our PIO program in the state machine
    pio_sm_set_enabled(pio, multislopeSM, true);
    irq_set_enabled(PWM_IRQ_WRAP, true);
    get_counts(pio, multislopeSM, 1);
   
    while(true){
        if (MeasurePLC==true){
        MeasurePLC = false;
        counts = get_counts(pio, multislopeSM, PWMcyclesPerMS);  //Multisloping for 20ms  (example)
        sample_ID++;
        difference = PWMcyclesPerMS - counts;  // PWMA and PWMB charge buckets counted during a single MScycle
        printf("%d, %d, %d, %d, %d, %d\n", sample_ID, counts, difference,
        auxADCresultPreMultislope, auxADCresultPostMultislope, (auxADCresultPostMultislope - auxADCresultPreMultislope));
      }
    }
..

Code: [Select]
55890, 0, 6000, 484, 1159, 675
55891, 0, 6000, 484, 1159, 675
55892, 0, 6000, 484, 1158, 674
55893, 0, 6000, 484, 1159, 675
55894, 0, 6000, 484, 1159, 675
55895, 0, 6000, 484, 1159, 675
55896, 0, 6000, 484, 1159, 675
55897, 0, 6000, 484, 1159, 675
55898, 0, 6000, 484, 1159, 675
55899, 0, 6000, 484, 1159, 675
55900, 0, 6000, 484, 1159, 675
55901, 0, 6000, 484, 1159, 675
55902, 0, 6000, 484, 1159, 675
55903, 0, 6000, 484, 1159, 675
55904, 0, 6000, 484, 1159, 675
55905, 0, 6000, 484, 1159, 675
55906, 0, 6000, 484, 1159, 675
55907, 0, 6000, 484, 1159, 675
55908, 0, 6000, 484, 1159, 675
« Last Edit: April 18, 2024, 10:28:47 am by iMo »
 

Offline Kleinstein

  • Super Contributor
  • ***
  • Posts: 14219
  • Country: de
Re: (Yet Another) DIY Multislope ADC
« Reply #59 on: April 18, 2024, 08:04:27 am »
The  TXCO's are impressive, but not really needed. There are quite some common xtal oscillators with jitter of around 1ps or better.  Jitter becomes relevant for the ADC noise when the jitter is higher than some 5 ps.  Old style 74HC... have jitter around 2 ps and the difference between a 74HC74 and 74AC74 is barely visible. Similar 74HC4053 gives slightly more noise then 74LV4053, likely from more jitter.

The µC internal PLL may well be the weak point. I have not found jitter data in the RP2040 datasheet. However they mention the compromise between jitter and power consumption for the choice of the VCO frequency. So jitter likely is somewhat noticable.  The DS for the STM32G071 (a possible alternative µC ) gives jitter specs of typical 40 ps RMS period jitter. This is quite a lot and would be a real issue. That µC would need to run without PLL and / or use external synchronization. The RP2040 may be slightly better, as it is not so much trimmed for low power.  However I don't expect is to be more than 40 times better than the STM32G  to reach the 1 ps range. For the ADC the frequency offset is in the 100 kHz range and thus a more difficult case than period jitter.

To avoid the extra noise from jitter the RP2040 based ADC would thus likely need expternal synchronization with an external flip flop. This would solve the jitter problem and also help with more determistic delay modulation. The clock on the RP2040 module could be a real issue (I got large INL errors with a crstal at an AVR). The PIO system should be powerfull enough to also do the crude phase lock from PIO clock to an external clock - so one could likely still use the PLL. The alternative may be a slower (e.g. 10-20 MHz) external clock for the µC and PIO system and than possibly skip the external flip-flop.

To keep things really simple, one could still use the RP2040 internal ADC. It is not very good with the bug that limits the good sections to some 9 bits. Depending on the rest of the MS-ADC design it can still be good enough. E.g. in my version I only really use some 7-8 bits.
I would really prefer the µC internal ADC and use an external oscillator and flip-flop for syncorinization.

In most cases one would not use USB in direct combination with the ADC function. Usually some isolation barrier is wanted between the high resolution ADC and the PC connection for EMI reasons.
Isolating USB is possible but tricky. It is much easier to have an isolated UART and than a UART to USB bridge (FT232 like or maybe a RP2040) for the PC connected side.
 

Offline iMo

  • Super Contributor
  • ***
  • Posts: 4795
  • Country: pm
  • It's important to try new things..
Re: (Yet Another) DIY Multislope ADC
« Reply #60 on: April 18, 2024, 08:21:33 am »
..
To keep things really simple, one could still use the RP2040 internal ADC. It is not very good with the bug that limits the good sections to some 9 bits. Depending on the rest of the MS-ADC design it can still be good enough. E.g. in my version I only really use some 7-8 bits.
I would really prefer the µC internal ADC and use an external oscillator and flip-flop for syncorinization..

But you are using rundown+auxADC, this design has none rundown, so I doubt the 2040's internal ADC would be suitable. In opposite, my guess would be to go even with a better auxADC in this desigh as is today.. (..I've found in my junkbox a nice MAX11166/67 16bitter in 3x3mm 12 pin package :) with true bipolar +/-5V input, perhaps usefull here). Another option here would be the introduction of a rundown..
 

Offline Kleinstein

  • Super Contributor
  • ***
  • Posts: 14219
  • Country: de
Re: (Yet Another) DIY Multislope ADC
« Reply #61 on: April 18, 2024, 09:20:35 am »
There were a few versions of the MS based ADC. The case with no rundown (thus MS3 or MS4 similar) would indeed want a better ADC and also relatively fast modulation. Ideally one would use the aux ADC in the fly (as with the HP meters) and thus not stop the intgration at all. This would allow to look at the residual charge for more than just the start and end and this way get additional resolution, a bit similar to SD ADCs.

Since they stopped the integration, I thought that they would also use at least a fast (full reference) rundown.
A fast rundown would reduce the demand on the ADC by about a factor of 50  (clock / modulation period).  PIO should also be able to do the fast rundown, though this may need a little more code. The rundown part is what really makes the PIO worth while - just the run-up part is easy also with PWM hardware and a normal µC.
 

Offline iMo

  • Super Contributor
  • ***
  • Posts: 4795
  • Country: pm
  • It's important to try new things..
Re: (Yet Another) DIY Multislope ADC
« Reply #62 on: April 18, 2024, 09:29:10 am »
In current PIO SM code there is a couple of instructions left (max number of PIO instructions is 32, shared among all 4 state machines in the particular PIO). Currently 23 instr is used.
A talented PIO guy may perhaps push the fast rundown into those 9 instructions..
When removing the dithering you may introduce a fast rundown esily, imho. When not removing the dithering you have to use the second PIO somehow if those 9 instructions left would be not enough, that would be complicated.
But what you get with the fast rundown here? When not switching to different ref voltages/currents the integrator's slope will stay the same, so you may count 0..31 (or 0..15??) SM clocks in a single fast rundown, imho..
PS: but sure, after the fast rundown you will end up closer to zero integrator output voltage, thus auxADC input voltage range could be much smaller..
« Last Edit: April 18, 2024, 10:13:20 am by iMo »
 

Offline NNNITopic starter

  • Contributor
  • Posts: 47
  • Country: de
    • YouTube channel
Re: (Yet Another) DIY Multislope ADC
« Reply #63 on: April 18, 2024, 11:36:33 am »
iMo: Thanks for taking the time to try and understand my design and work with it, it definitely helps a lot to have an outside perspective for new ideas and improvements. As diminddl already mentioned, the repository was essentially left as such after the last set of experiments in June/July 2023, so there are a lot of things unfinished and not properly documented. I am trying my best to finish up my existing project backlog (among other things) and hope to get back to it in a few months.

kleinstein: Thanks for the insight regarding jitter and its effects on a multislope ADC.

PCB.Wiz: Once again, thanks for providing more information regarding low-jitter clock sources. This is something I will be looking at in the future.

Regarding rundown - the previous 'test' version of this ADC did have a rundown phase implemented in PIO (see image attached) based on this paper: https://dspace.mit.edu/bitstream/handle/1721.1/84880/868678609-MIT.pdf?sequence=2. I had banding issues with that ADC as well. You can find the code here: https://github.com/NNNILabs/6.5-Digit-Multislope-ADC/tree/main/Multilslope%20IIA
 

Offline iMo

  • Super Contributor
  • ***
  • Posts: 4795
  • Country: pm
  • It's important to try new things..
Re: (Yet Another) DIY Multislope ADC
« Reply #64 on: April 18, 2024, 11:59:21 am »
Ok, so you went for 16 clocks up with the voltage, then down while counting the clocks till the comparator switched.
But that would require to not saturate somewhere..
I mean with a constant slope (using the same ref+ and ref- as during the runup), in 16 clocks (off 32) you would add up half of the full scale to the final residual voltage. Now, the question is where the final residual voltage typically ended up (before adding half of the full scale), such it all fits.
Like final residual voltage=8V (for example), plus 5V (16 clocks) = 13V that could be off the analog span.
« Last Edit: April 18, 2024, 12:40:37 pm by iMo »
 

Offline Kleinstein

  • Super Contributor
  • ***
  • Posts: 14219
  • Country: de
Re: (Yet Another) DIY Multislope ADC
« Reply #65 on: April 18, 2024, 03:01:45 pm »
Where the voltage ends after the normal run-up can vary with the input voltage. Chances are one can avoid the extremes a little, but not much more.  The headroom of the integrator may not be such an issue, especially if one has time to read the residual charge and does not need to do it very fast (e.g. on the fly).
Using a fixed step up for the start is possible, but not effective.  One can be more effective (faster and less need for integrator headroom) by also looking at the comparator for the initial up part:  go up for some 2 cylces past the comparator saying that the sign is right. One may need some minimum for the step to have more time for settling.  There are than mainly 2 cases, that can still be handled the same way:
a) a short up phase of the minimum length and than a possibly longer down phase for the end
b) a longer up phase and than only a short (e.g. 3 or 4 cycles) down phase, just to get the zero crossing from the same direction as in the case before.
So the result would have 2 extra reference times as contributions to the result.

Nominally the slope for the up-down part are linked to the power from the run-up steps.  If the pulses are rather short and settling not perfect one may need a small correction. Similar, when the positive and negatve ref. voltage are not exactly the same there is a small correction term for the variable time references are active. Depending on the hardware one may want those extra correction(s) or can get away without them.
 

Online PCB.Wiz

  • Super Contributor
  • ***
  • Posts: 1555
  • Country: au
Re: (Yet Another) DIY Multislope ADC
« Reply #66 on: April 18, 2024, 07:53:39 pm »
The  TXCO's are impressive, but not really needed. There are quite some common xtal oscillators with jitter of around 1ps or better.  Jitter becomes relevant for the ADC noise when the jitter is higher than some 5 ps.  Old style 74HC... have jitter around 2 ps and the difference between a 74HC74 and 74AC74 is barely visible. Similar 74HC4053 gives slightly more noise then 74LV4053, likely from more jitter.

The µC internal PLL may well be the weak point. I have not found jitter data in the RP2040 datasheet. However they mention the compromise between jitter and power consumption for the choice of the VCO frequency. So jitter likely is somewhat noticable.  The DS for the STM32G071 (a possible alternative µC ) gives jitter specs of typical 40 ps RMS period jitter. This is quite a lot and would be a real issue. That µC would need to run without PLL and / or use external synchronization. The RP2040 may be slightly better, as it is not so much trimmed for low power.  However I don't expect is to be more than 40 times better than the STM32G  to reach the 1 ps range. For the ADC the frequency offset is in the 100 kHz range and thus a more difficult case than period jitter.

There are also different forms of jitter spec, this from a Epson part, SG-210SCBA (now EOL?)   (0.3 to 19ps depending on jitter type)

plus you also need to worry about possible micro-step effects of crystals.

PCB.Wiz: Once again, thanks for providing more information regarding low-jitter clock sources. This is something I will be looking at in the future.
It's always interesting to do a refresh.
I found quite a few parts have 'come and gone', and it seems you can get high spec 2520 package parts for not much premium.
The appeal there is you can easily try a high spec part and see if there is really any measurable difference.

It's even possible to have dual operation, with High-Spec faster source user switched with a 12MHz Xtal or osc for booting.
« Last Edit: April 19, 2024, 07:29:52 am by PCB.Wiz »
 

Offline iMo

  • Super Contributor
  • ***
  • Posts: 4795
  • Country: pm
  • It's important to try new things..
Re: (Yet Another) DIY Multislope ADC
« Reply #67 on: April 19, 2024, 09:37:04 am »
..One can be more effective (faster and less need for integrator headroom) by also looking at the comparator for the initial up part:  go up for some 2 cylces past the comparator saying that the sign is right. One may need some minimum for the step to have more time for settling.  There are than mainly 2 cases, that can still be handled the same way:
a) a short up phase of the minimum length and than a possibly longer down phase for the end
b) a longer up phase and than only a short (e.g. 3 or 4 cycles) down phase, just to get the zero crossing from the same direction as in the case before..

So the key message here is to approach the "end zero crossing" always from the same side (for example from "positive side") in order to eliminate the "comparator hysteresis" errors.

The steps, for example, when talking PIO in this case, we want approach comparator always from the "positive" side:

0. runup ended, switch both Vref switches off
1. look at the comparator (2 SM clocks)
2. if comparator shows positive side - set Vref switches such the integrator's voltage goes down (1 clock)
3. count the SM clocks till comparator changes while crossing the zero (2 clocks per count)
4. send the count to MCU (1 clock)
..
2. if comparator shows negative side - set Vref switches such the integrator's voltage goes up (32 clocks)
3. switch Vref switches such the integrator's voltage goes down (1 clock)
4. count the SM clocks till comparator changes while crossing the zero (2 clocks per count)
5. send the count to MCU (1 clock)

Is that ok?

This has to fit inside the 9 instructions left..

« Last Edit: April 19, 2024, 03:47:04 pm by iMo »
 

Offline Kleinstein

  • Super Contributor
  • ***
  • Posts: 14219
  • Country: de
Re: (Yet Another) DIY Multislope ADC
« Reply #68 on: April 19, 2024, 12:02:16 pm »
There is no need to switch of the reference for the start of the rundown. One would ideally start with the reference (e.g. negative)  that is already active at the end of run-up. The runup can be  so to start with one ref. and end with the other.
Having the negative ref. phase for a fixed 32 cycles only if needed is not good. The idea is to always have a negative and positive phase, just with different lengths.

The steps would be like this:

count neg_ref loops
loop until the comparator detects a positive integrator voltage
maybe add a little delay (e.g. 2 to 4 cycles)  - could be used to send the first part of the result
switch the reference to positive
count pos_ref loops
loop until the comparator detects a negative integrator voltage

turn off the reference
send the rest of the result (pos_ref counts)

The loops to count and wait for the comparator could likely be 2 cycles long. One would be
JMP (X--)     ;  just count from $FFFF
JMP (PIN)     ;  jump up
and the other direction as
JMP (PIN)    ; leave loop
JMP (Y--)     ; jump up

 
The following users thanked this post: iMo

Offline iMo

  • Super Contributor
  • ***
  • Posts: 4795
  • Country: pm
  • It's important to try new things..
Re: (Yet Another) DIY Multislope ADC
« Reply #69 on: April 19, 2024, 04:34:38 pm »
This is now 32 instructions.
The assumption is the runup always ends up on the negative side (below zero)..

Code: [Select]
.program ms
.side_set 1
; 1 side set bit for the MEAS pin

; don't forget to enable auto push
start:
    set pins, 0         side 0
    mov X, !NULL        side 0              ; set X to 0xFFFFFFFF
    out Y, 32           side 0              ; read the number desired counts
    irq 0               side 0              ; first residue ADC reading
    out NULL, 32        side 0              ; stall until DMA finished reading the ADC

beginning:
    set pins, 1         side 1
    jmp pin pwmhigh     side 1
    set pins, 2         side 1 [15]
    jmp Y-- beginning   side 1 [13]
    jmp finish          side 0
   
pwmhigh:
    jmp X-- dummy       side 1 [15]
dummy:
    nop                 side 1 [11]
    set pins, 2         side 1
    jmp Y-- beginning   side 1
    jmp finish          side 0

finish:
    in  X, 32           side 0              ; push PWM to FIFO, after the push X=0, Y=0

; let us assume the runup finished on negative side
rundown:
    mov X, !NULL        side 0              ; set X to 0xFFFFFFFF
countX:
    jmp X-- loop1       side 0
loop1:
    jmp pin countX      side 0              ; if COMP==0 we are on positive side
   
    in X, 32            side 0              ; send X to FIFO
    mov X, !NULL        side 0              ; set X to 0xFFFFFFFF
    set pins, 2         side 0              ; set switch such we go downwards towards zero
   
countY:
    jmp pin rndwend     side 0              ; if COMP==1 we crossed zero, end
    jmp X-- countY      side 0              ; count Y
 
rndwend:   
    in X, 32            side 0              ; send Y to FIFO
   
    set pins, 0         side 0              ; set PWMA/PWMB off

    irq 1               side 0              ; second residue ADC reading
    out NULL, 32        side 0              ; stall until DMA finished reading the ADC

.wrap_target
dither:
    jmp !OSRE start     side 0              ; jump out of desaturation when the OSR has data
    set pins, 1         side 0              ; set pin polarity
    jmp pin dither      side 0              ; check if the integrator is still high
    set pins, 2         side 0 [1]
.wrap
« Last Edit: April 19, 2024, 04:55:26 pm by iMo »
 

Offline NNNITopic starter

  • Contributor
  • Posts: 47
  • Country: de
    • YouTube channel
Re: (Yet Another) DIY Multislope ADC
« Reply #70 on: April 19, 2024, 04:52:28 pm »
By the way, if the positive and negative reference current switch pins can also be incorporated into sideset, a lot of instructions can be saved. This is something I tested successfully, code attached. However, there are certain compromises. Since the delay cycles and sideset pins share the same 5 bits, the more sideset pins you use, the fewer delay cycles you can program. With this code, the duty cycles have changed from 1/16 and 15/16 to 1/8 and 7/8. There are also a few more nops, which to me seem like wasted instructions. However, there's not much that can be done regarding that.

Code: [Select]
.program ms
.side_set 3

;Additional notes:
;PWM duty: 1/8, 7/8

start:
mov X, !NULL           side 0
out Y, 32              side 0
;irq wait 0             side 0 ;IRQ
;out NULL, 32           side 0 ;IRQ

pwmstart:
jmp pin pwmhigh        side 5
jmp X-- pwmlow         side 3

pwmhigh:
nop               [3]  side 5
nop               [1]  side 5
jmp Y-- pwmstart       side 3
jmp finish             side 0

pwmlow:
nop               [3]  side 3
nop                    side 3
jmp Y-- pwmstart       side 3
jmp finish             side 0

finish:
in X, 32               side 0
;irq wait 1             side 0 ;IRQ
;out NULL, 32           side 0 ;IRQ

.wrap_target
dither:
jmp !OSRE start        side 0
jmp pin dither         side 4
nop               [1]  side 2
.wrap

Similarly, if a separate switch was used to short the integrator when no measurement is taking place, the dithering code can also be avoided. Of course, with a 4053 switch (triple SPDT) this is not possible, but with a modern (and arguably more suited to the job) part like the TMUX1134, this can be implemented.
« Last Edit: April 19, 2024, 04:55:15 pm by NNNI »
 

Offline iMo

  • Super Contributor
  • ***
  • Posts: 4795
  • Country: pm
  • It's important to try new things..
Re: (Yet Another) DIY Multislope ADC
« Reply #71 on: April 19, 2024, 05:14:20 pm »
Frankly, I would rather go opposite way - to increase the "delayed" counts in the runup, say 2x, and double the SM clock frequency.
That allows to count more clocks in the rundown.. (provided my math is ok).. :)
« Last Edit: April 19, 2024, 05:29:55 pm by iMo »
 

Offline NNNITopic starter

  • Contributor
  • Posts: 47
  • Country: de
    • YouTube channel
Re: (Yet Another) DIY Multislope ADC
« Reply #72 on: April 19, 2024, 05:36:17 pm »
There's probably a better way to handle that - push rundown to the second PIO instance with a lower clock divider. That way, the PIO instance that handles multislope runup can be run at a reasonable clock speed, and the rundown PIO instance can have higher resolution.

However, that brings me to the question: what's the advantage of rundown vs reading residue using an ADC?
 

Offline iMo

  • Super Contributor
  • ***
  • Posts: 4795
  • Country: pm
  • It's important to try new things..
Re: (Yet Another) DIY Multislope ADC
« Reply #73 on: April 19, 2024, 05:43:35 pm »
Using the second PIO is feasible, sure. We need to have the final design of the rundown ready and we may try to place that into the second PIO.
The small HW issue will be with the handling of the PWMA and PWMB signals, as those have to be manipulated from both PIOs then.

PS: Kleinstein likes to have the end of the runup at the negative side :). Years back I made tons of simulations here with the runup, but cannot remember how the runups ended up. My feeling is the runup may end up at both sides. Perhaps there is a trick..
« Last Edit: April 19, 2024, 05:51:03 pm by iMo »
 

Offline Kleinstein

  • Super Contributor
  • ***
  • Posts: 14219
  • Country: de
Re: (Yet Another) DIY Multislope ADC
« Reply #74 on: April 19, 2024, 07:11:28 pm »
One can have the runup end at a fixed state. The runup is a squence of 3 parts, e.g.:
1) fixed positive (short)
2) positive or negative depending on the comparator reading  (usually longer, like 10 x more than the short phases)
3) fixed negative  (short)
The code with more side effects already has such a sequence.


The way with just using the auxiliary ADC has a limited resolution for the resudual charge. One point here is that the ADC gain depends on the integrator gain and this includes the inegration capacitor.
With an old style PP or PS integration capacitor the thermal drift of the capacitance could limit the usable resolution from the auxiliray ADC. With a C0G capacitor this would be a bit less of an issue.
Especially with shorter integration like 1 PLC the runup part has only some 1000-6000 steps and thus maybe some 10-12 bits of resolution from this. Because of the start and stop part and with an not so ideal time for the comparator reading one can loose 1 or 2 bits. Getting more than 10 bits from a 1 PLC runup needs a relatively fast modulation and this can come with compromises. The rest would have to come from the auxiliry ADC.  It gets even worse as shorter integration. Unless one really goes for 14 or 16 bits one may run into quantization limits.

The rundown part adds resolution and thus less need for fast modulation and less demand on the auxiliary ADC. This way a µC internal ADC (e.g. 10 bits) can be suficient. It takes a little extra time for the rundown, but not that much to be a problem at 1 PLC  or slower.
 
The following users thanked this post: iMo


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf