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

0 Members and 2 Guests are viewing this topic.

Offline NNNITopic starter

  • Contributor
  • Posts: 47
  • Country: de
    • YouTube channel
(Yet Another) DIY Multislope ADC
« on: August 27, 2021, 07:04:31 am »
Hello!
This is my very first post here, and I think I have good reasons to be nervous - I've come back to the EEVBlog forums many times, since a lot of people have posted their multislope ADC designs here, and for some reason I feel mine is a little...simple. And there is also the fact that I don't own a DMM capable of measuring more than 3.5 digits.

With that being said, here is the story behind and the details of my multislope ADC.

I got started on this project because I got jealous of someone getting a Keithley DMM, so I said to myself: "I'm going to make my own!" Of course, I was only this confident because I'd read the Art of Electronics 3rd edition and knew there was something about similar high resolution DMMs. At first I wanted to make a delta-sigma ADC, but after trying to understand the maths behind it, I decided to try something simpler - namely a dual slope. I got as far as a simulation (https://tinyurl.com/ygr27pba) and making a perfboard prototype, but that didn't work so well and I'd moved on to a multislope, which was described in some detail.

I call the topology I came up with "free-running", because as long as a clock signal is present, the multislope keeps running. Here is a link to a simple simulation:  https://tinyurl.com/yes5kj7v

Surprisingly I got the thing to work on a breadboard, but of course, didn't make any measurements then because I knew it was pointless. I got a PCB made and I was able to make some first-order measurements, but was not able to get the residue measuring ADC working, and that had to be abandoned in favour of the second revision of the PCB, this time with much better parts and an LM399 voltage reference. The uC I ended up choosing was the Raspberry Pi Pico, since I got rather enamoured with it and the 500ksps 12-bit (yes, I'm aware of the quirks, I've read Mark Omo's website about it) ADC it has. Of course, there is a separate 3.3V reference for the ADC, I'm not relying on the noisy internal switcher. As for the actual software, a friend of mine is writing the code for me, and he had a brainwave - using the SPI protocol to provide a clock signal to the multislope, and reading the output of the D flip-flop on the falling edge of the clock signal to get the counts for which the negative reference was turned on, and with some maths you can figure out the time the positive reference was turned on and ultimately the input voltage. This approach worked, as seen in a video I made about it (the second half: https://www.youtube.com/watch?v=ucJOKAhCHTQ, and yep, that's my channel) and I hope with some calibration and residue measurement the readings will start to make sense. No way to test beyond 3.5 digits however...

I'm well aware of the limitations of my topology, especially the fact that each switch is turned on an unknown number of times for a given number of clock cycles, for that reason the PCB has a few jumpers to change the switch inputs to PWM, so I can implement some kind of constant switch cycles algorithm.

I have not been able to test the second revision of the PCB yet, since I've had some trouble finding the LT5400-1 resistor network, but I should be getting some soon and I'll post updates then!

In the meanwhile, here is the schematic and a picture of the board.

 
The following users thanked this post: cellularmitosis, bck, jaromir, doktor pyta, ogden, ch_scr, iMo

Offline RoGeorge

  • Super Contributor
  • ***
  • Posts: 6227
  • Country: ro
Re: (Yet Another) DIY Multislope ADC
« Reply #1 on: August 27, 2021, 07:09:37 am »
Congrats, the board looks very nice!   :-+

Online Kleinstein

  • Super Contributor
  • ***
  • Posts: 14233
  • Country: de
Re: (Yet Another) DIY Multislope ADC
« Reply #2 on: August 27, 2021, 07:34:56 am »
If you have trouble getting LT5400:  AFAIK the MORN networks have a compatible pinout, though no thermal pad at the bottom. For the not so high target, this should be well good enough.  The MORN networks may also be available with more resistor values (e.g. 20 K , 50 K).
The resistor R4,5,6,7 are nearly as important for the accuracy.

Just in case you plan the build / polulate another board. The OPA2197 is not the very best choice.  For the reference amplification part I would prefer an OPA2202 (less drift and LF noise).  For the Integrator it is OK though an OPA1642 would be lower noise. There is some advantage to have 2 separate OP for the integrator, so the ouput dirver does not effect the other OP that is setting the precision.

The feedback with the Flipflop makes this a very basic sigma delta ADC.
I may be worth looking at the old solartron DMMs / mark space ADC (e.g. US3918050): when adding a forcing signal one could get a fixed (and lower) switching frequency. The result could still be from the comparator timing directly.
 

Offline NNNITopic starter

  • Contributor
  • Posts: 47
  • Country: de
    • YouTube channel
Re: (Yet Another) DIY Multislope ADC
« Reply #3 on: August 27, 2021, 07:53:52 am »
Congrats, the board looks very nice!   :-+

Thanks, hope it works as well as it looks!
 

Offline NNNITopic starter

  • Contributor
  • Posts: 47
  • Country: de
    • YouTube channel
Re: (Yet Another) DIY Multislope ADC
« Reply #4 on: August 27, 2021, 08:00:09 am »
If you have trouble getting LT5400:  AFAIK the MORN networks have a compatible pinout, though no thermal pad at the bottom. For the not so high target, this should be well good enough.  The MORN networks may also be available with more resistor values (e.g. 20 K , 50 K).
The resistor R4,5,6,7 are nearly as important for the accuracy.

Just in case you plan the build / polulate another board. The OPA2197 is not the very best choice.  For the reference amplification part I would prefer an OPA2202 (less drift and LF noise).  For the Integrator it is OK though an OPA1642 would be lower noise. There is some advantage to have 2 separate OP for the integrator, so the ouput dirver does not effect the other OP that is setting the precision.

The feedback with the Flipflop makes this a very basic sigma delta ADC.
I may be worth looking at the old solartron DMMs / mark space ADC (e.g. US3918050): when adding a forcing signal one could get a fixed (and lower) switching frequency. The result could still be from the comparator timing directly.

Thanks for the suggestions!

I just took a look at the MORN networks and they are indeed cheaper than the LT5400 series, but Vishay does not seem to have them in stock as well. I tried to get some good +/-25ppm resistors for R4 - R7, but they were out of stock, so I think in the next revision I'll end up using more of the MORN/LT5400 resistor networks.

My op-amp choices were dictated by what LCSC had in stock, since I got this board JLC assembled. I'll definitely consider using separate op-amps for the integrators, I can see how having two separate ones will help.

I will definitely take a look at the Solartrons and the mark space ADC.

Thanks once again for the suggestions!

Attached below is the table I made for selecting op-amps, there was another column for slew rate based on which I chose the OPA2197/OPA197.
 

Online Kleinstein

  • Super Contributor
  • ***
  • Posts: 14233
  • Country: de
Re: (Yet Another) DIY Multislope ADC
« Reply #5 on: August 27, 2021, 09:02:21 am »
The choice at JCL is indeed a bit limited. At least they have the OP07 even as a standard part, which is a perfectly fine choice for the reference amplification.  Building an MS-ADC from the parts available at JCL would be a challange - though not impossible.

For the integrator the choice of OPs depends on the intendent integration time. With a relatively short integration (e.g. 20 ms) and switching between the signal and zero input even an TL072 is possible (I had this on the breadboard and still got to the 6 digit range). If a longer (e.g. > 200 ms) integration at a piece is planed / needed to get sufficient resolution (e.g. with the mark space like design) the low frequency noise would become an issue. Than a zero dift OP could be the better choice for the presicion setting OP at the integrator. This OP can use a lower (e.g. +-2 V) supply - there are than quite a few to choose from and a few even at JCL. An AZ OP may want an extra local feedback cap and input resistor. The output driving OP only needs to be fast ( e.g. > 5 MHz GBW would be nice, 10 MHz is good), but the noise hardly matters.
The slew rate is not important, as the OPs are used in the small signal range. A good OP (fast and precision) as a single OP integrator may also work if the reference resistors are equal.

If not limited to the footprint there are other resistor networks that could be used: e.g.  NOMCT (lower noise than NOMCA) and in the low cost corner also the ACAS series.  For the reference voltage there is no need to go for exactly 10 V. A gain of 1.5 or 1.33 would be OK too. For simplicity I used a gain of 2 in my design, though this needs a higher supply.  Using equal resistors and 2 or 3 in parallel / series can be an option, even with discrete resistors.
With reistors from the same reel, 25 ppm/K types may be good enough for the start, as the matching is often quite a bit better than absolute TC. One also usually only cares about a smaller temperature range.
 

Offline ali_asadzadeh

  • Super Contributor
  • ***
  • Posts: 1907
  • Country: ca
Re: (Yet Another) DIY Multislope ADC
« Reply #6 on: August 27, 2021, 09:28:53 am »
Shouldn't you Connect the 4053 part to +-12V supply!? it's power is only 3.3V and GND.
ASiDesigner, Stands for Application specific intelligent devices
I'm a Digital Expert from 8-bits to 64-bits
 

Online Kleinstein

  • Super Contributor
  • ***
  • Posts: 14233
  • Country: de
Re: (Yet Another) DIY Multislope ADC
« Reply #7 on: August 27, 2021, 09:49:50 am »
The 4053 swich does not need a higher supply. The switch directs the currents from the input or the references to either ground or the virtual ground at the integrator input. So the switch pins will see a votlage very close to ground (e.g. +-20 mV around ground). Even if things go wrong with the integrator feedback and the integrator input is no longer at ground, the current from the references and the input is limited by the resistors to a low level (e.g. 100 µA range).

The LV4053 needs the low supply to work with the logic levels too. 5 V supply would help the switches a little (lower resistance), but it than is boarderline with 3.3 V logic levels.
 
The following users thanked this post: ali_asadzadeh

Offline NNNITopic starter

  • Contributor
  • Posts: 47
  • Country: de
    • YouTube channel
Re: (Yet Another) DIY Multislope ADC
« Reply #8 on: August 29, 2021, 06:08:42 am »
ali_asadzadeh: What Kleinstein says is right - the switch nodes are more or less at 0V because of the integrator summing junction and the normally closed part of the switch being at ground - this is a current switched topology, and I can get away with powering the 4053 with 3.3V. I could have chosen a higher voltage, but since the 4053 does not have logic level translation for the inputs, and my microcontroller and logic runs at 3.3V.

Kleinstein: True, I've seen the OP07s used in the Solartron 7081 for the same purpose in one of Marco Reps' videos. It is a good op-amp, but there are better ones available, and for the sake of convenience I wanted to use the same op-amp type across the entire board - preferably a single and dual version of the same op-amp, hence OPAx197.

I did use the TL072 in the prototype, but I felt I could do better in terms of noise with a better op-amp choice. I'm not entirely sure about using auto-zero op-amps in the integrator, since I think only stability of offset/bias with temperature is more critical than having no offset. The multislope clock is 100kHz to 125kHz, so run-up should be in the order of 10s or 100s of ms. Maybe a faster clock would have benefitted, or some kind of amplifier at the integrator output, as I've seen on some designs.

Luckily I was able to get my hands on some LT5400-1s, I should be getting them soon and posting the first results here.
 

Online Kleinstein

  • Super Contributor
  • ***
  • Posts: 14233
  • Country: de
Re: (Yet Another) DIY Multislope ADC
« Reply #9 on: August 29, 2021, 08:57:13 am »
The refrence amplifier part is DC only. At DC / very low frequency the OP07 is supperior to the OPA197. In other places the OPA197 can be better.
The right OP for the job depends on the function.

The lower frequency end relavant for the integrator depends on the integration time. With 20 ms or 200 ms integration and thus a relevant frequency of 25 or 2.5 Hz  the OPA197 is still good and no need for an AZ OP. If you "only" want 6 digit resolution the OPA197 would even be OK for 2 seconds integration. With longer integration I would prefer the AZ OP. This requires 2 separate OPs obviously.

The needed intgration time to reach a given resolution depends on the resolution one gets in measuring the charge at the start and end.

The shown hardware seems to have 2 possible methods:
1) the comparator and the timing of zero crossing, like the solatron meters
2) the µC internal ADC to measure the voltage at the integrator, like the HP34401

For comparator method it is about timing resolution. The frequency of the modulation does not directly effect the resoluton. With some 100 ns timing resolution and 100 ms integration time one would be close to 6 digit resolution. It is still a bit less because there are 2 measurements and the references are stronger than the full scale input. So it would need more like 200-500 ms integration to get 6 digit resolution from the pure quantization limit.
The modulation frequency and thus the capacitor size effects the noise for the charge measurement. A smaller cap makes the comparator less critical as the slope is steeper. The extra amplifier (slope amplifier - quite often an NE5534 with 2 additional diodes in the feedback) after the integrator is there to help the comparator. It gives a first amplification stage with a known low noise and allows the comparator to switch faster.  Another, less obvious function of the slope amplifier is to get a defined and not too large bandwidth.  So there is sometimes an extra cap to slow down the slope amplifier, but usually just GBW divided by the gain is enough.

For the ADC way, the modulation frequency makes a difference, as with fast modulation the capacitor can be smaller and this more charge resoultion from the given voltage resolution. However a faster modulation also needs a faster ADC and more critical timing. A crude approximation for the  resolution is the auxiliary ADC steps times number of modulation periods divided by about 3.  For the start I would still not make the speed very high  - first get it working at all (less critical timing) and than think about optimization.

p.s.:
 I just has a look at the ciruit:  ideally one of the currently unused (grounded) inputs of the MUX should also get the raw 7 V reference as an optional input. This the more stable signal than the +-10 V to check the ADC gain.
« Last Edit: August 29, 2021, 09:00:10 am by Kleinstein »
 

Offline NNNITopic starter

  • Contributor
  • Posts: 47
  • Country: de
    • YouTube channel
Re: (Yet Another) DIY Multislope ADC
« Reply #10 on: August 29, 2021, 03:28:12 pm »
I thought that since the OP07 is an old part I might replace it with something new, but I'll take a look at the specifications of both again and maybe change it in the next version.

And yes, this is meant to resolve voltages only down to 1uV (hopefully with the same accuracy) so I don't think I need anything very fancy.

I did leave a lot of options open in terms of selecting run-down/residue measurement. For now, I want to do residue measurement since it does not need exceptional timing. The comparator and the analog switches can be operated by the microcontroller directly - what I was thinking was to try PWM, where the microcontroller outputs PWM in such a way as to have the positive and negative reference switch a constant number of times, and maybe use the comparator output to trigger an interrupt to update the duty cycle in such a way as to keep the integrator from saturating.

I did coincidentally take a look at the famous 1989 HP Journal with the article about the 3548A ADC, and noticed the amplifier before the comparator, but since I'm doing residue measurement I don't need it...for now.

Also the reference voltage is connected to one of the inputs of the MUX, the node is labelled 'RAW'.

Edit: I took a look at the datasheets of the OP07 and the OPA197, and yes, only the OP07 (specifically the AD one) specifies long term stability, so that is definitely something to consider. Thanks for the suggestion!
« Last Edit: August 29, 2021, 03:34:29 pm by NNNI »
 

Offline iMo

  • Super Contributor
  • ***
  • Posts: 4797
  • Country: pm
  • It's important to try new things..
Re: (Yet Another) DIY Multislope ADC
« Reply #11 on: August 29, 2021, 04:09:14 pm »
Double-check whether the OP07 gives you +/-10V output with +/-12V power.
The TI's OP07 DS shows 0.5uV/K and 0.4uV/month.
Would not be an OPA277 better one (0.1uV/K and 0.2uV/month), even we talk 399 ??
 

Online Kleinstein

  • Super Contributor
  • ***
  • Posts: 14233
  • Country: de
Re: (Yet Another) DIY Multislope ADC
« Reply #12 on: August 29, 2021, 08:07:54 pm »
The are more modern alternatives to the OP07 - the big pluse with the op07 is it't relatively good availability (even a standard part at JLC).
Getting 10 V out with a 12 V supply is very much boarderline - it may help at low current (e.g. add extra resistors to + or - 12 V to provide all the current and maybe a little more).
For a LM399 ref the OP07 is usually good enough. The resistors for the 7 to 10 V and 10 V to -10 V step are more critical.

1 µV resolution is possible, though not easy. It may need some averaging with the OPA197. In the shown circuit the OP in the integrator sees a noise gain of 3 (or 4 with an extra resistor at the input to reduce the effect of the R_on drift). This would result in about 1 µV_rms noise alone from the OPA197 in the integrator and longer integration would not help much, as there is 1/f noise.

1 µV accuracy with a 10 V range is not going to happen so easy. It may be the limit to call known errors to be acceptable, so a kind of good enough limit. However chances are there are some errors that will be larger. There are plenty of small effect that may cause errors in the low ppm range. A point that can cause some error is the nonlinear resistance of the 4053 r_on. This gives a small square law contribution with a positive sign to the ADC. The small resistors are good for low noise, but can increase the INL.

I would consider 100 µV Ok for the start, later maybe 10 µV if things go well. The OPA197 used as input buffer alone may give an error in the 10 µV range.

Using PWM to control the feedback is an OK idea - I also use this in my new version. However I use a timer interrupt to check only the comparator state once per cyle and than a binary modulation only. Using the comparator timing to get more information for a continuous PWM feedbach is possible, but a bit tricky. It may be easier to use the µC internal ADC also for the feedback.
 

Offline NNNITopic starter

  • Contributor
  • Posts: 47
  • Country: de
    • YouTube channel
Re: (Yet Another) DIY Multislope ADC
« Reply #13 on: November 05, 2021, 05:18:42 am »
It's been a while, but I have an exciting update: I finally got some LT5400 resistors, thanks to a certain ExtraSolar!
I'll start working on the multislope again after I finish the current project I have on hand, a fully discrete CC/CV linear supply.
 
The following users thanked this post: TiN

Offline NNNITopic starter

  • Contributor
  • Posts: 47
  • Country: de
    • YouTube channel
Re: (Yet Another) DIY Multislope ADC
« Reply #14 on: November 13, 2021, 05:08:38 pm »
It took me way longer than it should have, thanks to some problems uploading code to the Pi Pico (turns out that it is not recognized by the computer when powered externally with 5V) and a mistake in the PCB (ironically, the same one I made on the previous iteration of the board), but I finally got it working!
For now, this is the "free-running" mode where the thing just oscillates on its own with the provision of the clock signal, no measurements being made. The next step I have to take is coming up with an algorithm that implements the constant switch transitions in PIO, do the residue measurements using the in-built 12-bit ADC, maybe use timers to sync to 50Hz, and have the main processor do the maths to turn counts into volts.
 
The following users thanked this post: TiN, ogden

Offline NNNITopic starter

  • Contributor
  • Posts: 47
  • Country: de
    • YouTube channel
Re: (Yet Another) DIY Multislope ADC
« Reply #15 on: November 18, 2021, 04:29:22 am »
After a few days of work, I was able to implement a constant switch cycles algorithm on PIO.

This algorithm comes from Takovsky (familiar name around here...?) - it uses PWM to maintain a constant number of switch transitions in every cycle to make sure charge injection errors can be calibrated out. The PWM duty cycle switches between (in my case) 20% and 80% depending on the state of the integrator. This makes sure that there is always a zero crossing in every PWM cycle. Here is a link to a Falstad simulation where the PWM generator is implemented using some building blocks: https://tinyurl.com/yfhwuvol

The PIO code was implemented by my collaborator Dimin, who is working on the software.

For now, we have this free-running again, the next thing to implement would be generating N PWM cycles and counting how many times each reference was turned on for 80% of the duty cycle, and then converting those counts into volts. The last step would be to add a residue measuring ADC.
 
The following users thanked this post: doktor pyta

Offline NNNITopic starter

  • Contributor
  • Posts: 47
  • Country: de
    • YouTube channel
Re: (Yet Another) DIY Multislope ADC
« Reply #16 on: December 19, 2021, 06:38:28 pm »
It has been a while since my last post, but I have not been idle.

I did a lot of research about different multislope algorithms, and I'm going to mention two here.

While I was waiting for code ( I outsource coding :palm: ), I was wondering what kind of topology I could make using just some simple logic I had on hand, and what I came up with was a bounded integrator topology - the integrator waveform oscillates between a set positive and negative limit. This is accomplished using a JK flip-flop (4027) clocked at an arbitrary frequency - the higher the frequency, the less chances of over/undershoot and more resolution. The limit comparators are hooked up to the J and K inputs in a way that turns on the respective ref switch to keep the integrator within bounds. Here is a link to a Falstad simulation: https://tinyurl.com/y6g6yans
Since the slopes are much longer, the number of transitions per clock cycle is considerably lesser than the other topologies I've tried - depending on the clock, the bounded integrator topology has around one transition every 10+ clock cycles, free running has between one transition every clock cycle or less, while the PWM method has exactly two transitions per clock cycle. I assumed that keeping the number of transitions as low as possible would reduce problems due to charge injection. Transitions per clock is a very loose measure of charge injection.
Of course, this method is not without its problems - for one thing, the overall frequency of the integrator ramps changes with changing input up to 50%...initially this didn't seem like a problem to me until I realized that the measurement time would have to vary if I wanted a fixed number of slopes, that is, the counts per clock changes with changing input voltage. One more glaring issue is dielectric absorption, which has plenty of room to manifest itself with slow slopes, which leads to loss of linearity. I was later informed that I had partially re-invented the Solartron 7081 ADC, except that I didn't have that weird square wave injection circuit. I have attached a few images of this bounded integrator that I built on a breadboard.

Since I felt like I was waiting around too much for code, I explored the possibilities of making the PWM algorithm work using discrete logic ICs, and I did end up making something using an 8:1 mux (HC151, for example), a binary counter (HC193) and a D flip-flop (4013): https://tinyurl.com/y4xps42r
Making the whole thing using logic would be finicky but not difficult - have the microcontroller generate a clock, pulse a pin to start conversion, and read back the output of the counters using PISO shift registers.  Of course, just using microcontrollers would be the easiest way out, but I found this little thought experiment fun, and along the way did a lot of thinking about the way results are derived from the PWM topology.
Going the logic way, each PWM cycle takes up (in my case) 8 clock cycles, so it would be possible to get 8 counts per PWM cycle, that is, one count per clock cycle. but since the first and last part of the PWM waveforms cancel each other out (duty cycle is either 12.5% or 87.5%, so the first 12.5% and the last 12.5% cause charges of the same magnitude but opposite polarity in the integrator, so they cancel out) and the main counting happens in the difference in duty cycle extremes. So ultimately it comes down to one count per PWM cycle, or one count every 8 main clock cycles.

With all this boring theory out of the way, I will focus on getting the code up and running and actually post results.

Found this interesting paper: https://dspace.mit.edu/bitstream/handle/1721.1/84880/868678609-MIT.pdf?sequence=2
 
The following users thanked this post: sorin

Online Kleinstein

  • Super Contributor
  • ***
  • Posts: 14233
  • Country: de
Re: (Yet Another) DIY Multislope ADC
« Reply #17 on: December 19, 2021, 09:11:44 pm »
The vesion with simple fixed bounds for the upper and lower limit has the problem with a variable frequency. The DA effect is actually not bad, as the slower part of the DA depends on the average voltage in the integrator. So this part would be rather small.

To get closer to the Solartron working one could use time dependen bonds. So that with time the bonds get lower. The exact waveform for the bonds does not matter, so it could be some RC fitlered rectangular waveform or piecewise linear. The only point is to keep the waveform stable, or use a 3rd comparator for the actual zero crossing. With suitable modified bonds one can get a constant frequency for the PWM signal. The difference to the Solartron (mark - space type) ADC is that the forcing waveform is moved to the other side of the comparators.
A week point of such a contineous integrating ADC is the somewhat limited resolution (~ 0.7 * Integration time / timing resolution ) and that the integration time can vary a bit whern the signal and thus the waveform is not stable. For a fixed time one could in theory read the residual charge with an ADC, like in the HP34401. This may also get a little more resolution than just the timing.

With a constant swtiching frequency the charge injection is not the real problem. It would be only variations in the charge injection that matter. There is still more sensitivity to clock jitter when switching is more often.
 

Offline NNNITopic starter

  • Contributor
  • Posts: 47
  • Country: de
    • YouTube channel
Re: (Yet Another) DIY Multislope ADC
« Reply #18 on: December 20, 2021, 05:56:31 am »
Reading residual charge using an ADC is what I was initially planning, and I will experiment with that too, but the only problem with that is that it involves some math and needs to keep track of the timing between the residue measurements. It requires that both the main conversion and the residue reading be converted to volts before they can be added together, but the dual slope rundown described in that paper produces counts that can be directly combined with the main counts, and then converting counts to volts takes place in the last step. Also, the fixed number of bits of rundown is convenient.
 

Offline NNNITopic starter

  • Contributor
  • Posts: 47
  • Country: de
    • YouTube channel
Re: (Yet Another) DIY Multislope ADC
« Reply #19 on: January 12, 2022, 08:42:30 pm »
This might be a bit premature, but I got to finish the 3D printed case and the power supply...and the results are terrible - I could have done a much better job. The only reason I'm pushing it is because I might actually have to use this to make (crude) measurements soon.
As for the software, still working on it. Since I'm using PIO, getting the timings is proving to be a challenge. However, I think I might have just the right person to help me.
Hopefully I'll be able to post actual data and statistics soon.
 

Offline NNNITopic starter

  • Contributor
  • Posts: 47
  • Country: de
    • YouTube channel
Re: (Yet Another) DIY Multislope ADC
« Reply #20 on: January 15, 2022, 08:26:36 pm »
Finally got the PIO PWM timings right! now the duty cycle is an exact 1/16 and 15/16, with a frequency of 200kHz which keeps the integrator swing to more or less +/-5V over the entire input range.
The second picture presents something more interesting - I was running the multislope for 50 PWM cycles with input disconnected (i.e., corresponding analog switch turned off), and after every 50 cycles the integrator voltage went up by a small bit. I think this is because of charge injection from the 4053 analog switch, so I zoomed out on the scope (second image), and the integrator voltage did increase linearly. The multislope was running for around 250us every 1 second, and at 10 seconds per division you can see how the integrator voltage in yellow goes up a little bit, and the result is a nice and linear ramp. This is good news because it confirms that charge injection effects are indeed linear (at least at this temperature and supply voltage) and can be calibrated out.
 
The following users thanked this post: ogden

Online Kleinstein

  • Super Contributor
  • ***
  • Posts: 14233
  • Country: de
Re: (Yet Another) DIY Multislope ADC
« Reply #21 on: January 15, 2022, 09:17:14 pm »
With a constant switching frequency the charge injection part is essentially constant and thus easy to subtract. It is just part of the offset.

The slight shift that happens represents the offset of the ADC input and there are multiple contributions to it. The more important are:
Asymmetry in the references (from resistors and OP offset)
Tolerances in the resistors for the +10 V and -10 V ref.
The offset of the "slow" OP at the integrator
leakage currents at the 4053
mismatch in 4053 resistance
input bias at the integrator
net charge injetion
pulses in the residual voltage at the integrator input voltage, that can be slightly asymmetric for the 2 directions

It is a good sign that the drift rate seen is about constant. This gives hope to not have large nonlinear effects depending on the integrator output voltage. There may still be small INL contributions, as for the final result it is about some 100 µV or so ín the integrator voltage after some 20 ms, or some 5 mV after a second.  The time with the integrator in hold mode is naturally not causing much errors.
 

Offline NNNITopic starter

  • Contributor
  • Posts: 47
  • Country: de
    • YouTube channel
Re: (Yet Another) DIY Multislope ADC
« Reply #22 on: January 28, 2022, 07:54:28 pm »
It is finally time for the first super-crude results!
So I got the timings right and input sorted out, so just for the hell of it I set the ADC up to do one reading per second, 5000 PWM cycles so 5000 counts with no residue reading. I took 1990 readings over something like half an hour and made a histogram (inspired by https://pico-adc.markomo.me/INL-DNL/), and the results actually looked interesting.
Next, measuring in PLCs and rundown residue.
 

Offline NNNITopic starter

  • Contributor
  • Posts: 47
  • Country: de
    • YouTube channel
Re: (Yet Another) DIY Multislope ADC
« Reply #23 on: April 06, 2022, 04:55:48 am »
Another rather disappointing update.
The first picture (yellow - integrator, blue - positive reference switch, pink - negative reference switch, dark blue - input switch) shows a sample multislope cycle: "Desaturation", which is reading the comparator and setting one of the reference switches so that the integrator goes to zero so it does not start with a random charge. This was a problem that caused noisy results. Second, of course, is PWM - 1/16 and 15/16 duty cycle. Then comes pre-rundown, which adds a constant dummy charge to the integrator to make sure it is negative for the next step - rundown. Rundown involves ramping the integrator up till zero is reached and counting the number of cycles it takes to do so.
Initially, I tried one PLC of measurement followed by one PLC of integrator zero, but added a lot of noise to the result, so I changed to 20PLC worth of continuous integration (200ms).
The results, however, are rather interesting. There is still quite a bit of noise on the ADC, but there also seems to be some kind of bug that causes two "groups" of readings, as shown in the second picture. A count is worth 10uV.
Of course, I do not know what the bug is yet, but given how hastily and poorly designed this ADC is, I want to start fresh with better parts and better PCB layout and better practices in general. It was an interesting experiment and I learnt a lot from it.
 

Online Kleinstein

  • Super Contributor
  • ***
  • Posts: 14233
  • Country: de
Re: (Yet Another) DIY Multislope ADC
« Reply #24 on: April 06, 2022, 06:18:06 am »
The 2 groups of result look indeed like a bug (SW problem). As the noise is quite high even the "noise" could still be a SW problem.

Much of the noise looks like it effects both groups and would thus be rather low frequency noise. The 1/f noise could be a problem and it may be worth considering to alternate between a conversion from the input an one from 0 V and than look at the difference only.

The ADC circuit has a few weak points, but overall it does not look that bad and I would expect better performce should be possible.
I looks a bit like there could be quite some overshoot at the integrator (could as well be the ground hook at the scope probes). A good testpoint for the integrator is the ouput of U6B, so the "slow" OP in the compound integrator. This should give a kind of rectangle signal with some overshoot, but not too much ringing. From my experiences and simulations it may need some resistance (e.g. 100 ohms range) in series to C19 to dampen ringing.

It could be a good idea to have some kind of filtering BW limit between the integrator and comparator. The slope amplifier found in many implementations between the integrator and comparator also has the task to limit the bandwidth.

A weakness in the circuit as shown is that the resistance for the input in twice the resistance for the references. This leads to incomplete compensation of the drift of the switch on resistance. So ideally there should be the same resistance,even of this means a slightly small input range (like +-8 V) only.

For testing it may still help to first look at short integration and possibly even a more dual slope like mode with seperate input and reference integration. This gives less resolution and mode noise, but makes errors more visible.
With only a single slope for the run-down the resolution is quite limited. There are 2 options to add a smaller slope with relatively little effort even to the existing PCB:
1) add a resistor (e.g. 1 M range) from the +7 V ref. to the integrator input. So there would be no more stop mode but slow drift instead. This would be similar to the small slope in the Keithley 2000

2) add a resistor (e.g. 220 K) in parallel to R7 and this make the references a little asymmetric. Than the case with both reference channels actice acts as small slope. This however needs a little more math in looking at the result. This is like my ADC solution works.
 

Offline MegaVolt

  • Frequent Contributor
  • **
  • Posts: 918
  • Country: by
Re: (Yet Another) DIY Multislope ADC
« Reply #25 on: April 06, 2022, 08:57:16 am »
Two groups of readings can cause popcorn noise of the reference source.
 

Offline NNNITopic starter

  • Contributor
  • Posts: 47
  • Country: de
    • YouTube channel
Re: (Yet Another) DIY Multislope ADC
« Reply #26 on: April 06, 2022, 10:35:35 am »
Kleinstein, thanks for your suggestions. I'm not sure if I want to continue experimenting with this board, I already have a long list of improvements planned for a next revision including a slope amplifier and maybe the addition of some kind of slow slope. Another idea on my mind was to convert the reference voltages to currents like in the K2002.

MegaVolt, do you mean the input voltage or the ADC reference? In any case, that thought never occured to me, thanks for the information.

Meanwhile, I measured a 9V battery over around 6000 measurements. The histogram maybe meaningless for a drifty measurement, but the scatter plot looks interesting...now the readings have diverged into sets  |O .
 

Online Kleinstein

  • Super Contributor
  • ***
  • Posts: 14233
  • Country: de
Re: (Yet Another) DIY Multislope ADC
« Reply #27 on: April 06, 2022, 10:57:44 am »
Using current sources like in the K2002 is quite some extra effort with relatively little return. On the downside on no longer gets compensation for the drift in the on resistance of the switch for the input channel.

The splitting of the signal looks to be too large to be caused by popsorn noise (either the ADC reference or the external reference for the test voltage).
The line split in 4 really looks like a SW problem, like missing a count or PWM value update (and thus having one step twice). The difference between the curves may give a clue.

For an initial test of the noise the usual test point is 0 input and thus no reference noise for the source and ideally no effect of reference noise for the ADC side.

The slowly drifting votlage source is also a good test, as this can show DNL errors and possible weak points where the ADC does not work well.
 

Offline NNNITopic starter

  • Contributor
  • Posts: 47
  • Country: de
    • YouTube channel
Re: (Yet Another) DIY Multislope ADC
« Reply #28 on: April 06, 2022, 09:22:19 pm »
I tried the method Kleinstein suggested of measuring input and then zero and considering the difference between them. I also averaged 10 readings. Each input and zero reading was 1PLC. The results look slightly better.
 

Offline NNNITopic starter

  • Contributor
  • Posts: 47
  • Country: de
    • YouTube channel
Re: (Yet Another) DIY Multislope ADC
« Reply #29 on: August 27, 2022, 08:58:01 pm »
It's been a long while since I posted updates here, and a lot has happened!
I designed a completely new set of PCBs with better layout, and got it working, complete with software. I was able to run a few INL tests (compared to Keithely 2000), and I got a reasonable inverted parabola, which is a good sign which means linearity could be better with tweaking. However, the readings are very noisy, and I narrowed it down to problems with residue readings.
I'm using an MCP3202 ADC IC to do the job. Reference voltage and supply is 3.3V from a 3.3V LDO, 1uF bypass capacitor on the power pin. Since the readings were noisy, I decided to investigate the ADC alone, and on feeding a constant voltage into it I got readings that were insanely noisy (hundreds of counts), and there was also "banding". On zooming in closer, some codes are also missing. I have no idea what is causing this.
 
The following users thanked this post: cellularmitosis

Offline branadic

  • Super Contributor
  • ***
  • Posts: 2392
  • Country: de
  • Sounds like noise
Re: (Yet Another) DIY Multislope ADC
« Reply #30 on: August 29, 2022, 12:52:24 pm »
Are you sure your ADC scaling is correct? If not, that could explain the "banding".
Have you checked the MCP3202 ADC independently on a breadboard with shorted input? Maybe you have some weird coupling effects that affect your noise readings.

-branadic-
Computers exist to solve problems that we wouldn't have without them. AI exists to answer questions, we wouldn't ask without it.
 

Offline julian1

  • Frequent Contributor
  • **
  • Posts: 735
  • Country: au
Re: (Yet Another) DIY Multislope ADC
« Reply #31 on: August 29, 2022, 07:32:17 pm »
Also review the code used to read the adc. I used mcp3208 for a project, and found it a bit fiddly to set up the control bits for input - either differential or single-ended. As well as flipping the spi read bytes by the adc to match the endiness of the mcu. The grouping/clustering of values could be explained by a problem handling the conversion.
 

Offline NNNITopic starter

  • Contributor
  • Posts: 47
  • Country: de
    • YouTube channel
Re: (Yet Another) DIY Multislope ADC
« Reply #32 on: August 30, 2022, 09:59:01 am »
branadic: These are raw counts from the ADC, so I don't think it's a matter of scaling constants this time. But maybe it might have something to do with the layout, that is something I'll have to confirm later.
julian1: I've attached the code used to this post.
 

Offline MegaVolt

  • Frequent Contributor
  • **
  • Posts: 918
  • Country: by
Re: (Yet Another) DIY Multislope ADC
« Reply #33 on: August 30, 2022, 10:06:20 am »
Apply a slowly varying signal to the input. I think a lot will become clearer. Perhaps there is a problem with the order of the bits.
 

Online Kleinstein

  • Super Contributor
  • ***
  • Posts: 14233
  • Country: de
Re: (Yet Another) DIY Multislope ADC
« Reply #34 on: August 30, 2022, 10:54:21 am »
There are still too many codes coming up to be a problem with just the order of the bits. That much noise looks more like a problem with the supply, reference or the clock (e.g. way to fast or too slow).
 

Offline NNNITopic starter

  • Contributor
  • Posts: 47
  • Country: de
    • YouTube channel
Re: (Yet Another) DIY Multislope ADC
« Reply #35 on: June 14, 2023, 10:29:26 pm »
I've finally figured out why the residue ADC readings were so bad - turns out that there's something in the software that is returning the wrong pair of readings for a given charge balancing cycle.
The first image shows what is going on graphically.
The second image is the raw readings from the ADC. Column B and C are "before" and "after" residue ADC readings respectively, and the blue highlighted numbers are the difference between the two. If I move the values in column B one row up and then take  the difference with C, the results are the ones highlighted in green, consistent expected values.
I was able to figure this out by reading the voltage on the integrator during the residue readings manually while making single-shot measurements, the values in column C were consistent with what I was seeing on the scope, while column B was not.
 
The following users thanked this post: iMo

Offline iMo

  • Super Contributor
  • ***
  • Posts: 4797
  • Country: pm
  • It's important to try new things..
Re: (Yet Another) DIY Multislope ADC
« Reply #36 on: April 11, 2024, 12:49:35 pm »
Hi, I've been playing with your SW (rp2040 with PIO state machine) and have couple of questions perhaps, if I may..
My current understanding is following:
1. you set rp2040's clock to 96MHz
2. SM's clock is set to 52.1ns (96/5)
3. the PWMcycle is set inside PIO for 32 SM clocks with 2:30 duty, thus I see the "2" (for example) aprox 105ns long on my scope, in total the PWMcycle=1.66us (=32*52.1ns) I can see here, is that correct?
4. the "MScyclesPerPLC" is the number of "PWMcycles in 1PLC measurement period", thus with 50Hz it should be 12000 (you have there 6000), imho (because 20ms/1.66us is 12000), is that correct?
5. in "final" this line should be
Code: [Select]
//uint32_t counts = get_counts(pio, multislopeSM, pwmCycles); //Multisloping for 20ms
uint32_t counts = get_counts(pio, multislopeSM, MScyclesPerPLC); //Multisloping for 20ms
as the pwmCycles (12 in your source) there is for testing purposes only, is that so?.
I've been running it on a waveshare's rp2040-Zero..
Tnx!

« Last Edit: April 11, 2024, 01:22:05 pm by iMo »
 

Offline iMo

  • Super Contributor
  • ***
  • Posts: 4797
  • Country: pm
  • It's important to try new things..
Re: (Yet Another) DIY Multislope ADC
« Reply #37 on: April 12, 2024, 09:58:51 am »
Hi, as the rp2040 PICO with its PIO state machine engines is a pretty interesting gadget for multislope experiments, I have commented in a little bit better detail what is happening inside the PIO assembler program for the state machine providing the MS events in NNNI's design.

I've done it such the algo is somehow readable for people who mess with the PIO asm first time (inclusive myself), it may contain errors, for information only.
I will update or remove it when NNNI will update his MS on the github.

PS: corrected my many typos..  :D

Code: [Select]
;
; The PIO asm program for the MUltislope 3
; by NNNI in https://github.com/NNNILabs/Multislope-3I/tree/main/SW
; commented in detail by iMo 04/2024
;
; PWMB and PWMA is a GROUP of TWO OUTPUT PINS ("pins"), manipulating switches for positive nad negative REFERENCE charges
; BOTH PWMA and PWMB pins are manipulated in a single cycle, shall be adjacent pins, PWMA being the lower bit
; MEAS is a so called "sidepin" (you may set/clr the sidepin within any asm instr) - here the OUTPUT PIN indicating a running MS cycle (an MS cycle consist of "N" PWM cycles)
; COMP is the INPUT PIN ("pin") wired to the comparator
;
; this program does 32 clocks long PWM cycles (PWMA and PWMB) with a duty of 2:30
; the number of switchings within one MS cycle should be kept constant by this algo
; the "clock" frequency and pins/pin assignments are set outside this PIO program
; the residual voltage measurements are done via CPU0 (an external ADC), based on
;   the irq0 (at the MS start) and the irq1 (at the MS end) signals issued by this PIO SM machine
; outside the MS cycle this program provides constant "dithering" of the integrator input (toggling PWMA and PWMB)
;
; the C part of the system
; 1. writes the required number "N" of PWM cycles to PIO's Y register (like 6000 for example)
; 2. reads the residual voltage at the beginning of the MS cycle (via SPI through the CPU0)
; 3. reads the number of PWMA charge buckets counted during the MS process
; 4. reads the residual voltage at the end of the MS cycle (via SPI through the CPU0)
; the number of PWMB buckets is equal (N - PWMA)


.program ms
.side_set                                   ; one "side set" bit is the MEAS pin, when 0 we do not count PWMs cycles/buckets, when 1 we do count

; don't forget to enable auto push
start:                                      ; here we start a single MS cycle
set pins, 0             side 0              ; this sets GROUP of two pins [PWMB, PWMA] = [0, 0], MEAS = 0
    mov X, !NULL        side 0              ; set X (number of PWMA charges) to initial 0xFFFFFFFF, we will count down at each bucket, MEAS = 0
    out Y, 32           side 0              ; read from input FIFO the desired number of MS PWM cycles (like 6000 for example) and put it into Y, MEAS = 0
    irq 0               side 0              ; first residue ADC reading, done via SPI via DMA by the CPU0, MEAS = 0
    out NULL, 32        side 0              ; stall until DMA finished reading the ADC into the CPU0, MEAS = 0

beginning:                                  ; the beginning of one MS Measurement cycle, ie 20ms long, with fixed count of ie. 6000 PWM cycles
    set pins, 1         side 1              ; set [PWMB, PWMA] = [0, 1] and set MEAS = 1
    jmp pin pwmhigh     side 1              ; pin is the COMP input pin, if 1 jump to pwmhigh, MEAS = 1
    set pins, 2         side 1 [15]         ; set [PWMB, PWMA] = [1, 0], and stay so for additional 15 clocks, MEAS = 1
    jmp Y-- beginning   side 1 [13]         ; decrement Y at each PWM bucket polarity regardless, jmp if not 0 to a new PWM cycle, stay so for 13 additional clocks, MEAS = 1
    jmp finish          side 0              ; jmp to finish of the MS cycle and set MEAS = 0 (end of MS cycle)
   
pwmhigh:                                    ; when pwmhigh we decrement X (PWMA)
    jmp X-- dummy       side 1 [15]         ; decrement X and stay for additional 15 clocks, jmp if not 0 (it never be 0), MEAS = 1
dummy:
    nop                 side 1 [11]         ; do NOP and stay for additional 11 clocks, MEAS = 1
    set pins, 2         side 1              ; set [PWMB, PWMA] = [1, 0], MEAS = 1
    jmp Y-- beginning   side 1              ; decrement Y at each PWM bucket polarity regardless, jump to new PWMcycle if not 0, MEAS = 1
    jmp finish          side 0              ; jmp to finish of the MS cycle and set MEAS = 0 (end of MS cycle)

finish:
    set pins, 0         side 0              ; set [PWMB, PWMA] = [0, 0], MEAS = 0
    in  X, 32           side 0              ; push the X value (number of PWMA charge buckets) to FIFO (will be read by CPU0 via FIFO), MEAS = 0
    irq 1               side 0              ; perform the second final stage ADC residue reading via SPI (done by CPU0), MEAS = 0
    out NULL, 32        side 0              ; stall until DMA finished reading the ADC, MEAS = 0

.wrap_target                                ; this is an endless "desaturation loop" (between wrap_target and wrap) keeping integrator input around ZERO when not doing the MS cycle
dither:                                     ; we toggle PWMA and PWMB in a loop around ZERO integrator voltage
    jmp !OSRE start     side 0              ; jump out of this desaturation loop when the OSR has data (it means the CPO0 has sent the "N" at the beginning of the MS cycle), MEAS = 0
    set pins, 1         side 0              ; set [PWMB, PWMA] = [0, 1], MEAS = 0
    jmp pin dither      side 0              ; check if the comparator output pin is still 1 and jump to dither if 1, MEAS = 0
    set pins, 2         side 0 [1]          ; set [PWMB, PWMA] = [1, 0], stay so for additional 1 clock, MEAS = 0
.wrap
« Last Edit: April 12, 2024, 01:02:18 pm by iMo »
 
The following users thanked this post: ch_scr

Online Kleinstein

  • Super Contributor
  • ***
  • Posts: 14233
  • Country: de
Re: (Yet Another) DIY Multislope ADC
« Reply #38 on: April 12, 2024, 11:29:16 am »
There should be no need to have the reference modulation that fast. 96 MHz and 16 cycles would be modulation frequency of 6 MHz. For comparison the HP3458 uses some 330 kHz. With a good capacitor there is no need for more than some 50 kHz to reduce the DA effect on the INL sufficient.

A very fast modulation also comes with downsides: Charge injection gets more important. The integrator settling gets more important and really fast settling integrator is wanted. More time is lost to the fixed short pluses needed for settling. This limits the usefull range (looks like  4/16 of the range are lost in this example). Jitter and becomes more relevant as a noise source. Even worse may be other delays (ps range is enough) caused in the µC that can cause INL errors.

Even without such a fast modulation one may want to consider separate syncronization to a stable clock (e.g. with 74AC74 flip flops) to avoid juster and delay modulation from the µC. This would likely be with a slower clock not 96 MHz anyway.

The RP2040 could still be interesting as it may be able to run the ADC part in parallel to normal operation. AFAIK the µC internal ADC has some flaws so that the usable resolution is more like 8 or 10 bits.
 

Offline iMo

  • Super Contributor
  • ***
  • Posts: 4797
  • Country: pm
  • It's important to try new things..
Re: (Yet Another) DIY Multislope ADC
« Reply #39 on: April 12, 2024, 12:20:27 pm »
In his example as of today on his github a single pwm modulation cycle is made of 32 clocks, where the clock is set to 96MHz/5=19.2MHz.
The single pwm cycle is therefore 1.67us (say 600kHz). It is perhaps his testing setting. You may set the PIO's SM clock as you wish (CPU_clock/div). I've been running the code on my rp2040-zero and I can see that timing on the scope. You may overclock CPUs (there are 2) to 300-400MHz max, btw.

All the instructions above are single clock (say 5ns at 200MHz), with additional prolongation of any instruction, and the sidepin(s) set/clr in parallel as well - that is a pretty impressive combination.

For example a single 1 clock instruction

jmp Y-- beginning   side 1 [13]

decrements the 32bit register Y, jumps to "beginning" label if Y is not 0, sets a "sidebit" output pin to 1, and makes this instruction 14 clocks long.. Imagine what could you do with your MS ADC design if you had this gadget handy..


You may have 2 PIO instances with 4 SMs in each, DMAing the SM'es data via a 4/8 words deep in/out FIFOs into/from the CPU0 or CPU1 (or any peripherals, afaik). No need to use an external FPGA for many apps. The 9 instr assembler is not easy to read, and there is a lot of various tricks you may do with it as well, so one need some time to get grip on it..
« Last Edit: April 12, 2024, 01:09:24 pm by iMo »
 

Online Kleinstein

  • Super Contributor
  • ***
  • Posts: 14233
  • Country: de
Re: (Yet Another) DIY Multislope ADC
« Reply #40 on: April 12, 2024, 05:09:14 pm »
The PIO part should be capable to control a MS ADC. The limiting factor is however not so much the digital control part, but the analog part (e.g. settling of the integrator with 2 x OPA140 or similar) takes some 200 ns or so. So the shortest pulses should be no less than some 500 ns to get reasonable good settling. This sets a practical limit for the modulation speed of some 200-300 kHz - faster gets sensitive to settling effects or looses quite some of the input range.

The speed for the modulation is a compromise. Fast allows to use a small integration capactor and thus allow low residual charge noise (only relevant for short integration). Fast modulation also allow a fast rundown and gets less INL from DA. One the other side faster modulaton gets you more INL error from settling effects, more INL error from delay modulation, more noise from jitter, switch capacitance and noise in the charge injection.

My ADC version uses the µC internal ADC and here the ADC inside the RP2040 is not that great, though still OK. The RP2040 would need an external comparator - other µC can incluce the comparator.

The main point where fast control and also fast modulation could really make a difference is when it comes to a fast rundown to get really fast conversions (e.g. > 10000 SPS).  However for really fast conversion the MS-ADC (especially the version with a rundown) may not be the best choice anyway.  Modern SAR chips and also some SD ADC chips get pretty good at 100 kSPS or 1 MSPS.
 

Offline NNNITopic starter

  • Contributor
  • Posts: 47
  • Country: de
    • YouTube channel
Re: (Yet Another) DIY Multislope ADC
« Reply #41 on: April 14, 2024, 11:16:40 pm »
First off: Extremely sorry for not replying to the previous messages sooner. I am unfortunately not very active here, and somehow I completely missed the fact that this thread had replies (I don't get E-Mail notifications).

iMo did send me a private message regarding the topic of this thread, but somehow it never occurred to me to check. I will read the messages and questions in detail and get back as soon as possible.

I was wondering why the GitHub repo for the project was suddenly getting so many stars, never occurred to me that it might be from here...

diminddl, who is collaborating with me on this project and is responsible for the software side, wrote a post on Hackaday explaining the code: https://hackaday.io/project/190528-multislope-adc/log/217945-code-overview, I hope this answers some questions.
« Last Edit: April 14, 2024, 11:40:06 pm by NNNI »
 

Offline NNNITopic starter

  • Contributor
  • Posts: 47
  • Country: de
    • YouTube channel
Re: (Yet Another) DIY Multislope ADC
« Reply #42 on: April 15, 2024, 09:36:40 am »
Regarding the modulation frequency: Yes, the PIO clock divider is set to 5 for testing.

The original intention of the 96MHz underclock (I have stably overclocked the RP2040 to 400MHz) was to have a PIO clock divider of 10 to get a 9.6MHz PIO clock. That results in each PIO instruction taking 1.04167us. Each PWM cycle is 32 clock cycles long, and therefore a period of 3.333us (300kHz modulation frequency). This was chosen so there would be an integer number of PWM cycles in both a 50Hz and 60Hz PLC (20ms/3.333us = 6000 PWM cycles, 16.667ms/3.333us = 5000 PWM cycles).
 

Offline iMo

  • Super Contributor
  • ***
  • Posts: 4797
  • Country: pm
  • It's important to try new things..
Re: (Yet Another) DIY Multislope ADC
« Reply #43 on: April 15, 2024, 09:59:13 am »
I've been playing with the digital part, getting familiar with the PIO+MCU combo..
I've wired my junkbox MAX1247 ADC and running the modded test chunk of code, watching what is going on. Of course I've played with various settings. My ADC works fine with 2MHz SPI clock, with LM385-2.5V ref and 1N4148 (5mA If) as the source I get rock stable reading with occasional 1LSB excursion for both pre- and -post MS readings (btw. all on a solderless breadboard with jumpers and my pico-zero dingsbums). Also my pico has got linear voltage regulator.

The first residual measurement occurs 20-40us (it depends on ADC SPI clock) before the start of the MS cycle, that might be too long before the MEAS=1, I guess. It is because you wait on DMA reading the ADC SPI.
Why not use an another channel for ADC, such it reads the ADC in parallel with the beginning of the MS cycle?
Simply issue the irq0, wait for ADC_acquisition time (perhaps 1-2us) and do not stall the PIO during the ADC SPI DMA..

PS: in the MCU section I've asked whether we know the typical jitter of the clocks generated by the rp2040 pll. Soon or later somebody here will ask that too (as the clock jitter has been identified as a potential troublemaker with 6+ digits).. :)
Worst case you may run the MCU off an external 50MHz canned oscillator.
« Last Edit: April 15, 2024, 10:14:05 am by iMo »
 

Online Kleinstein

  • Super Contributor
  • ***
  • Posts: 14233
  • Country: de
Re: (Yet Another) DIY Multislope ADC
« Reply #44 on: April 15, 2024, 10:10:40 am »
300 kHz modulation period for the run-up sounds much more sensible (similar to 34401 and 3458), though still relatively fast. It may be needed for the MS3 (34401) like version with no rundown. Otherwise fast modulation makes jitter more relevant and with just the RP2040 there is a chance for quite some jitter from the PLL. For the jitter I can see the difference between an 74HC74 and 74AC74 for synchronization, even with slower modulation (~100 kHz).
 

Offline iMo

  • Super Contributor
  • ***
  • Posts: 4797
  • Country: pm
  • It's important to try new things..
Re: (Yet Another) DIY Multislope ADC
« Reply #45 on: April 15, 2024, 10:22:58 am »
The 2040 strategy with jitter is to set the internal pll as close as possible to 1500MHz, and then divide down to say those 125MHz (or other  cpu clock). Then the jitter should be lowest, DS says. For example the Si570 gadgets worked with 4.7GHz pll and achieved pretty low jitter, perhaps the 2040 follows that too (better it needs to be measured, considering their ADC design flaw).

« Last Edit: April 15, 2024, 11:27:50 am by iMo »
 
The following users thanked this post: ch_scr

Offline NNNITopic starter

  • Contributor
  • Posts: 47
  • Country: de
    • YouTube channel
Re: (Yet Another) DIY Multislope ADC
« Reply #46 on: April 15, 2024, 10:42:40 am »
Quote
Why not use an another channel for ADC, such it reads the ADC in parallel with the beginning of the MS cycle?
This is exactly what I was planning and working on last year.
« Last Edit: April 15, 2024, 10:47:34 am by NNNI »
 

Offline iMo

  • Super Contributor
  • ***
  • Posts: 4797
  • Country: pm
  • It's important to try new things..
Re: (Yet Another) DIY Multislope ADC
« Reply #47 on: April 15, 2024, 04:24:17 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).
« Last Edit: April 15, 2024, 04:46:07 pm by iMo »
 

Online PCB.Wiz

  • Super Contributor
  • ***
  • Posts: 1555
  • Country: au
Re: (Yet Another) DIY Multislope ADC
« Reply #48 on: April 17, 2024, 12:59:42 am »
The 2040 strategy with jitter is to set the internal pll as close as possible to 1500MHz, and then divide down to say those 125MHz (or other  cpu clock).
Yes, the VCO's are usually current controlled oscillators, giving the best jitter at higher power/highest MHz.

For example the Si570 gadgets worked with 4.7GHz pll and achieved pretty low jitter, perhaps the 2040 follows that too (better it needs to be measured, considering their ADC design flaw).

re Si570 area : If you want to look at cased i2c oscillators here is table I drew up a while back, that shows jitter-GHz are certainly related, and they tend to use higher MHz, xtals for lower jitter. (and probably smaller size too)

Code: [Select]
~~~~~~~~~~~~~~~~ SiLabs i2c Oscillators ~~~~~~~~~~~~~~~~~~~~
Device SpeedGrade Xtal    Out(MHz.CMOS) MinFvco(GHz)    MaxFvco(GHz)   Icc         Jitter
 Si564.A         152.6    0.2~3000     10.8            13.122222222    87mA CMOS   95fs RMS 
 Si549.A         152.6    0.2~1500     10.8            12.511886114    87mA CMOS   95fs RMS
 Si549.B         152.6    0.2~800      10.8            12.206718160    87mA CMOS   95fs RMS
 Si549.C         152.6    0.2~325      10.8            12.206718160    87mA CMOS   95fs RMS 
 Si544.A          55.05   0.2~1500     10.8            12.550082103    74mA CMOS   150fs RMS
 Si544.B          55.05   0.2~800      10.8            12.109728345    74mA CMOS   150fs RMS
 Si544.C          55.05   0.2~325      10.8            12.109728345    74mA CMOS   150fs RMS
 Si564.A          3GHz out $42
 Si570           114.28   10~160M      4.850           5.670           90mA CMOS   0.62pstyp
 Si599            39.17   10~810       4.85            5.67            90mA CMOS   0.7ps     
 Si514           31.98MHz 0.1~250M     2.080           2.500           21mA CMOS   0.8ps     
 Si5351A.QFN20   25~27    0.002~200    0.6             0.9             22mA CMOS   ~40ps pp 
 Si5351A.MSOP10  25~27    0.002~200    0.6             0.9             22mA CMOS   ~70ps pp 

Those are highly flexible but not especially cheap.

Over in the Audio sandpit, there are many complex oscillators offered up, but this one looks to be simple, using a 74LVCU04 gate
https://www.diyaudio.com/community/attachments/twtmc-p-pdf.615086/
Note they use a large can, custom crystal when chasing extreme numbers.

Addit3: I found another variant, a Pico gate Pierce, shows the crystal matters most for low Hz phase noise.
https://www.thewellaudio.com/wp-content/uploads/TWTMC-PPG-V2_User_Manual.pdf
Note they test here with batteries and shielded.

At the simpler end, Nisshinbo offer a NJU6385, in a DFN6 package,

https://www.nisshinbo-microdevices.co.jp/en/products/quartz-crystal-oscillator-ic/spec/?product=nju6385
that part claims impressive low jitter and noise. (I think tested at 49.152MHz )

●Phase noise
 -103dBc/Hz(Typ.) @10Hz Offset
 -163dBc/Hz(Typ.) @1kHz Offset
●RMS Jitter 0.05psec(Typ.) @12kHz to 20MHz

Not much mention of power supply, but these inverter oscillators would likely benefit from a modern, low noise local regulator.

It's hard to tell how much secret sauce is in that NJU6385, or if it is just a DFN packaged standard unit ?
ie how much better is it really, than a 74LVCU04 or 1GU04 oscillators above ?
The Pico gate info above, suggests less secret sauce, but NJU6385 is small and includes C and biasing.
Mouser do stock the similar NJU6311, in MSOP10, with divider choices.


The lowest ESR crystal generally available looks to be ABLS-LR-12.000MHZ-T in HC-49/US (SMD) ESR <15 Ohms

Addit: Another option point, for high end instruments like ADC's, could be crystals like ECS's aged models :  a slight premium on jellybean crystals.
Their ESR is higher, than the larger ABLS-LR, but they have been pre annealed/aged  - maybe that matters more ?

ECS-120-10-33B-CKM-TR3  12.000 MHz 10 pF ECS-33B 10/10 ppm -20 ~ +70C 1 ppm Aging 3225  ESR <100 Ohms
https://ecsxtal.com/news-resources/how-ecs-inc-b-series-crystal-oscillators-support-your-future-forward-technology/

That looks easy to retro fit onto a RP2040 board, as I think they use 3225 commonly.

Addit2: Another reference point on the KISS/Cost/performance curve, is to simply bolt on the 'best TCXO' like the ATX-H12-F-12.000MHz-F25-T
Numbers are a tad worse than the NJU6385 claims, but it's all in one package, and spec'd out of the box.
An alias/branding clone of that ATX-H12 looks to be the FT2MHUPM12.0, showing stock at Newark, strangely a bit cheaper than the ATX-H12, at under $2 ?
These Abracon parts spec (ATX-H12 / FT2MHUPM12.0)
Phase Noise (@ 10 MHz Carrier, @ 25°C ±2°C)
@10Hz offset      -98 dBc/Hz Typical  -94 dBc/Hz Max
@100Hz offset    -122 dBc/Hz Typical -118 dBc/Hz Max
@1kHz offset     -145 dBc/Hz Typical -141 dBc/Hz Max

That would be easy to add to a RP2040 board, to check.
« Last Edit: April 18, 2024, 12:02:01 am by PCB.Wiz »
 
The following users thanked this post: ch_scr, iMo, NNNI

Offline iMo

  • Super Contributor
  • ***
  • Posts: 4797
  • Country: pm
  • It's important to try new things..
Re: (Yet Another) DIY Multislope ADC
« Reply #49 on: April 17, 2024, 06:03:04 am »
Yep, I collected many various Si570s (20y back while messing with the first SDR radios), afaik they output till 1.5Ghz based on the part number suffix and type of output, cmos till 160MHz-250MHz, lvds till 1.5Ghz. Expensive, indeed.
Now, how the rp2040 does perform? :)
« Last Edit: April 17, 2024, 06:05:17 am by iMo »
 

Online Kleinstein

  • Super Contributor
  • ***
  • Posts: 14233
  • 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: 4797
  • 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 »
 

Online Kleinstein

  • Super Contributor
  • ***
  • Posts: 14233
  • 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: 4797
  • 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 »
 

Online Kleinstein

  • Super Contributor
  • ***
  • Posts: 14233
  • 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: 4797
  • 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: 4797
  • 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 »
 

Online Kleinstein

  • Super Contributor
  • ***
  • Posts: 14233
  • 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: 4797
  • 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..
 

Online Kleinstein

  • Super Contributor
  • ***
  • Posts: 14233
  • 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: 4797
  • 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: 4797
  • 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 »
 

Online Kleinstein

  • Super Contributor
  • ***
  • Posts: 14233
  • 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: 4797
  • 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 »
 

Online Kleinstein

  • Super Contributor
  • ***
  • Posts: 14233
  • 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: 4797
  • 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: 4797
  • 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: 4797
  • 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 »
 

Online Kleinstein

  • Super Contributor
  • ***
  • Posts: 14233
  • 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

Offline iMo

  • Super Contributor
  • ***
  • Posts: 4797
  • Country: pm
  • It's important to try new things..
Re: (Yet Another) DIY Multislope ADC
« Reply #75 on: April 19, 2024, 07:40:31 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..

That ends the runup at the "fixed negative" part 3), but where does the "voltage level" end at the end of the 3rd part above?

PS: I've been asking that because in case the runup voltage ends "above zero", we have to provide similar/symmetrical rundown sequence as we did when it ended "below zero" (on the negative side) as well. Both will not fit in the PIO_0.
« Last Edit: April 19, 2024, 08:08:51 pm by iMo »
 

Online Kleinstein

  • Super Contributor
  • ***
  • Posts: 14233
  • Country: de
Re: (Yet Another) DIY Multislope ADC
« Reply #76 on: April 19, 2024, 08:14:05 pm »
The voltage at the end can be positive or negative depending on the input voltage. Usually one can not exclude one sign or the other. So a rundown would have to cope with both cases I am afraid
 

Offline iMo

  • Super Contributor
  • ***
  • Posts: 4797
  • Country: pm
  • It's important to try new things..
Re: (Yet Another) DIY Multislope ADC
« Reply #77 on: April 19, 2024, 08:25:32 pm »
Now, when we agree the runup's end voltage may end up anywhere (positive or negative), would be above "positive" and "negative" symmetrical rundown sequences work fine?

As I indicated above a recommendation I saw somewhere said the rundown sequences (starting at positive or negative voltage) have to approach (at their end) the comparator always from the same side (ie positive) in order to compensate for comparator's hysteresis (and perhaps for other errors too).. That means they cannot be symmetrical.

An example is the Landsberg's rundown NNNI implemented in his MS II - you go always up into positive (positive or negative runup's end voltage regardless) and then down to zero (crossing zero from the same positive side of the comparator).
« Last Edit: April 19, 2024, 08:48:16 pm by iMo »
 

Online Kleinstein

  • Super Contributor
  • ***
  • Posts: 14233
  • Country: de
Re: (Yet Another) DIY Multislope ADC
« Reply #78 on: April 19, 2024, 08:46:41 pm »
The two step run-down can work with any starting charge. It just needs a little (but not much) heatroom for the start.  The sequence is not really symmetrical, but it is still the same sequence of steps, just different times.  So not just the same direction for the end, but also all the reference transitions in the same sequence, just with 2 variable times. A condition can be the any of the phases should not be too short as settling at the integrator takes some time.
 

Offline iMo

  • Super Contributor
  • ***
  • Posts: 4797
  • Country: pm
  • It's important to try new things..
Re: (Yet Another) DIY Multislope ADC
« Reply #79 on: April 19, 2024, 09:01:13 pm »
Frankly, I've been looking for a symmetrical perfectly deterministic rundown..
Those not fully symmetrical rundowns with varying/different times etc lead to a voodoo where one juggle with esoteric 15 digits floating point coefficients in order to get a reasonable results..   ::)
 

Online Kleinstein

  • Super Contributor
  • ***
  • Posts: 14233
  • Country: de
Re: (Yet Another) DIY Multislope ADC
« Reply #80 on: April 19, 2024, 10:19:05 pm »
The rundown part is only a relatively small part of the result. The question is only if the reference for the rundown are more accurate than a high resolution ADC and stable capacitor, that would be the alternative.
If the postive and negative reference are the same size, not extra constant is needed to calculate the result. Ideally the difference between the reference (including a possible offset of the integrator input voltage) is an additional correction parameter, that has a limited effect. Measuring that parameter is relatively simple by comparing the case of no reference and both references at the same time. It is a little extra effort for a kind of "factory calibration", but the later math is not so bad.  No need to go above some 16 bits, as the rundown part is still only a relatively small part of the result.

How would a fully symmetric rundown look like ?  Only one direction and thus a comparator reading from both directions is not really a good option. It adds the comparator hysteresis / delay problem and also the problem with a very short pulse close to zero initial charge.
A fixed sequence with 2 variable times is kind of the natural choice. The system is fully determistic. There is no big difference from starting positive of negative. At zero res. charge one gets 2 short pulses and when away from zero one of the pulses gets longer and the short one stays the same.  There is just some freedom in the design on how short the pulses can get. Adding a few more cycles there is usually not such an issue.
A possibly tricky point may be the effect of short pulses in the runup. This way the runup steps may be tiny bit different from just the ref. strength and time. In the shown simple runup scheme the number of short pulse directly follows the runup result and a slightly modified cal. constant could compensate. With not too fast a modulation and thus enough time for the short pulses this should still not be a problem.
 

Offline iMo

  • Super Contributor
  • ***
  • Posts: 4797
  • Country: pm
  • It's important to try new things..
Re: (Yet Another) DIY Multislope ADC
« Reply #81 on: April 20, 2024, 07:24:47 am »
So the above routine for the rundown should work as follows (as per KL's description as I have understood it), we have Vref+ and Vref- both 10V (please comment below sequence in VERY DETAIL directly in the below text describing the steps, such we may understand and close this rundown stuff finally and test):

***********
0. the runup phase ended, the residual voltage RV is somewhere between +/-10V
Rundown:
1. when the comparator shows RV is below zero Volt set Vref switch such we go UP with RV, otherwise set Vref such we go DOWN with RV, reset X
2. count with X the SM clocks till the comparator crosses the zero Volt
3. send X to FIFO, set the Vref switch to the opposite direction, reset X
4. count with X the SM clocks till the comparator crosses the zero Volt
5. send X to FIFO
6. switch off both Vrefs such the integrator is on hold
Residual ADC reading:
7. do the second auxADC reading
***********
etc..

Thus at the end of single PLCcycle measurement we got
a) preADC value,
b) PWMA runup counts,
c) PWMB runup counts,
d) rundown X counts,
e) rundown Y counts,
f) postADC value.

Is that OK?
« Last Edit: April 20, 2024, 08:01:48 am by iMo »
 

Online Kleinstein

  • Super Contributor
  • ***
  • Posts: 14233
  • Country: de
Re: (Yet Another) DIY Multislope ADC
« Reply #82 on: April 20, 2024, 09:20:24 am »
The way it is described would use the comparator in different directions and do the extra wiggle for the other direction, that is a bit pointless.
Depending on the direction one will get a quite different residual charge from the reaction time (comparator and synchornization in the µC and possible external to the clock).
The problem is already the step 1.  The idea is not getting a symmetry in the procedure, but a fixed sequency on how the reference switches.

The first part should always be the same reference (ideally the one that is active at the end of runup anyway). So no need to look at the comparator first. This reference would be used even if it moves the integrator a little bit away from zero.

So no looking at the comparator in step1 and always the same ref. (e.g. negative).
The 2nd step is than not waiting for a zero crossing, but wait for the right sign (e.g. positive). The right sign may be present already from the start and than this counting look will be just one pass.
To have enough setting time one may have to add a little delay before switching the reference to the other value (e.g. positive). Sending the first counts may be enough delay.

The next step is than a similar counting loop for the other sign (e.g. always positive). At the end both reference would be off.
If the first counting loop had to do more loops the overshoot is small and the 2nd loop will be close to the minimum length.
If there is time (e.g. longer integration) one could wait a little to let the fast part of the DA and the ampölifier settle before doing the resudual ADC conversion.

The result would not need separate PWMA and PWMB counts for the runup, as the total count for the steps is fixed (e.g. given as a parameter to set the integration time). So counting one side is enough.
 

Offline iMo

  • Super Contributor
  • ***
  • Posts: 4797
  • Country: pm
  • It's important to try new things..
Re: (Yet Another) DIY Multislope ADC
« Reply #83 on: April 20, 2024, 06:51:38 pm »
Quote
The 2nd step is than not waiting for a zero crossing, but wait for the right sign (e.g. positive).

What is the "right sign"? Right sign of what?

We have only three (3) things here during the rundown process at hand:
1. Vref switch PWMA
2. Vref switch PWMB
3. output of the comparator, which could be "0", or "1", where one input of the comparator is Grounded (0 Volt).

"Waiting on zero crossing" means we wait till the RV (Residual Voltage, here it is the same as "integrator voltage") voltage goes from "negative" to "positive", or from "positive" to "negative", where zero is 0 Volt.

Quote
The first part should always be the same reference (ideally the one that is active at the end of runup anyway). So no need to look at the comparator first. This reference would be used even if it moves the integrator a little bit away from zero.

Where (by what) your "right sign" is indicated? How I get the information on the right sign when the RV moves away of zero?
« Last Edit: April 20, 2024, 07:39:04 pm by iMo »
 

Online Kleinstein

  • Super Contributor
  • ***
  • Posts: 14233
  • Country: de
Re: (Yet Another) DIY Multislope ADC
« Reply #84 on: April 20, 2024, 08:46:57 pm »
The counting lops are waiting for a comparator output and this sign of the integrator output voltage.
 

Offline iMo

  • Super Contributor
  • ***
  • Posts: 4797
  • Country: pm
  • It's important to try new things..
Re: (Yet Another) DIY Multislope ADC
« Reply #85 on: April 21, 2024, 06:46:23 am »
The counting lops are waiting for a comparator output and this sign of the integrator output voltage.

Our counting loops above wait for a comparator output, so I still have pretty hard time to understand how is your idea on this simple rundown process in this design like..

I would be happy to formalize that simple rundown process based on your valuable hints, but I am not native English speaker, so perhaps the problem is on my side..
 

Online Kleinstein

  • Super Contributor
  • ***
  • Posts: 14233
  • Country: de
Re: (Yet Another) DIY Multislope ADC
« Reply #86 on: April 21, 2024, 07:42:46 am »
Maybe it is easier to show a suggested code for the rundown. I hope I got it right - I have not used the RP2040 PIO programming thus far.
The code part would be just after the run-up part and before starting the residue ADC. 

Code: [Select]
.program run-down
.side_set 3
; 3 side bits for ref. pos(1) + neg(2) + meas(4)
; meas could be done separate if more delay is needed

   in X, 32            side 2              ; send X to FIFO (runup-counts), ref to neg , input off   
   mov X, !NULL        side 2              ; set X to 0xFFFFFFFF 
   
count_neg:   
   jmp pin end_neg     side 2
   jmp X-- count_neg   side 2              ; count , jump to close the loop
   
end_neg:
   in X, 32            side 2 [3]           ; send X to FIFO (counts for neg ref.) , some delay for minimum pulse length for settling

count_pos:   
   jmp X-- cout        side 1              ; count , no real jump
cont:
   jmp pin count_pos   side 1   

count_end:
   in X, 32            side 0              ; send X to FIFO (counts for neg+pos ref.)

    ; add some delay ( more like a loop for a few µs to allow the amplifier and fast DA to settle)
    ; start the residue ADC

 

Offline iMo

  • Super Contributor
  • ***
  • Posts: 4797
  • Country: pm
  • It's important to try new things..
Re: (Yet Another) DIY Multislope ADC
« Reply #87 on: April 22, 2024, 07:30:38 am »
Thanks, so you have combined the first comparator check (whether we are on the negative or positive side) with counting when we are already on positive side (thus counting the negative charge till zero Volt) after runup's end.

Thus,
1) when the integrator's voltage at the start of the rundown was negative (COMP==1), the result will be X=0+POS,
2) when the integrator's voltage at the start of the rundown was positive (COMP==0), the result will be X=NEG+0.

Having 3 sideset bits would limit the instr. stretching in runup to max +3  (instr [3]), however..
With MEAS in "set" it will be +7, which allows 1:8 modulation and might perhaps fit..

« Last Edit: April 22, 2024, 07:46:51 am by iMo »
 

Offline iMo

  • Super Contributor
  • ***
  • Posts: 4797
  • Country: pm
  • It's important to try new things..
Re: (Yet Another) DIY Multislope ADC
« Reply #88 on: April 22, 2024, 08:25:11 am »
This is with 1:8 modulation, MEAS is the single set bit, PWMA/PWMB/INPUT two sidebits (in the below source marked as "P" and they need to be set accordingly in the final source).
It looks like it is now 31 instructions, but the instr. have to be doublechecked..
The dithering loop could be perhaps made of less instr. now..
After the rundown there is enough time for settling as the auxADC is called via interrupt and it samples around the middle of the first 8 SPI bits (it depends on the ADC chip used), moreover you may stretch the instructions before the second auxADC as well.

PS: so we get following results off a single PLC measurement

1. pre- auxADC reading
2. runup count
3. rundown's negative charge count
4. rundown's negative+positive charge count
5. post- auxADC reading

Code: [Select]
.program ms
.side_set 2
; 1 set bit for the MEAS pin
; 2 sideset bits for PWMA/PWMB/INPUT setting

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

beginning:
    set pins, 1         side P              ; MEAS=1
    jmp pin pwmhigh     side P
    set pins, 1         side P [7]          ; was 15
    jmp Y-- beginning   side P [5]          ; was 13
    set pins, 0         side P              ; MEAS=0
    jmp finish_rup      side P             
   
pwmhigh:
    jmp X-- dummy       side P [7]          ; was 15
dummy:
    nop                 side P [3]          ; was 11
    set pins, 1         side P              ; MEAS=1
    jmp Y-- beginning   side P
    set pins, 0         side P              ; MEAS=0
    jmp finish_rup      side P              ; MEAS=0

finish_rup:
    in X, 32            side P              ; send X to FIFO (runup-counts), ref to neg , input off

rundown:
    mov X, !NULL        side P              ; set X to 0xFFFFFFFF
   
count_neg:   
    jmp pin end_neg     side P
    jmp X-- count_neg   side P              ; count , jump to close the loop
   
end_neg:
    in X, 32            side P [3]          ; send X to FIFO (counts for neg ref.) , some delay for minimum pulse length for settling
   
count_pos:   
    jmp X-- cout        side P              ; count , no real jump
cont:
    jmp pin count_pos   side P   
   
count_end:
    in X, 32            side P              ; send X to FIFO (counts for neg+pos ref.)
   
rundown_end:
    irq 1               side P              ; second residue reading
    out NULL, 32        side P              ; stall until DMA finished reading the ADC

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

Online Kleinstein

  • Super Contributor
  • ***
  • Posts: 14233
  • Country: de
Re: (Yet Another) DIY Multislope ADC
« Reply #89 on: April 22, 2024, 09:44:37 am »
The 8:1 modulation may be a bit to little. So one would ideally want a longer delay for the mittle part of the runup. There is no need to limit this to an easy binary ratio like 1:8 or 1:32.

Especially with the rundown one usually wants a relatively fast clock and thus longer delay.

In the code the very start with set pin = 0  to turn off the input is not really needed. once the ADC has run it will end with meas = 0.  If the conversion is aborted, one would needed to discharge the integrator anyway, as it may well be saturated.
So one could skip the first command.
The code is still a mix of using side channel and set pins (for the dithering part). As it is tricky to add delay otherwise it may be better to not use the side channels.

The 2 rundown cases are not really 0 + pos or neg + 0. The other reference is still used for a short sime. The positive part is not even fixed, it can still vary a littlel (like +-1 cout) from noise and comparator hysteresis.

 

Offline iMo

  • Super Contributor
  • ***
  • Posts: 4797
  • Country: pm
  • It's important to try new things..
Re: (Yet Another) DIY Multislope ADC
« Reply #90 on: April 22, 2024, 10:10:09 am »
Perhaps it is feasible to stretch out some instructions inside the runup loops such we will get a better modulation ratio.
Not using sidebits here may add up the "set" instructions, imho, and it may not fit into the 32 instructions then.

Now we are at 31. Hopefully the X register does not zero itself after the "in X, 32" instruction, then you would have to set it to "FF.." and we are at 32.

As we basically have the preADC+runup+rundown+postADC+dithering framework "ready", people may start to try to optimize the code further on.

PS: removing the "dithering" and moving "sideset" signals to "set" (thus none sideset bits) would allow up to 1:32 modulation ratio, and perhaps 5bits (+/- 1LSB) rundown resolution..
« Last Edit: April 22, 2024, 11:43:56 am by iMo »
 

Offline iMo

  • Super Contributor
  • ***
  • Posts: 4797
  • Country: pm
  • It's important to try new things..
Re: (Yet Another) DIY Multislope ADC
« Reply #91 on: April 22, 2024, 12:48:52 pm »
Here it is with all three signals in "set pins", none in sideset, modulation (for example) set to 2:64 clocks.
None dithering.
The rundown part not tested yet as I do not have the analog part handy.
The runup timings of the PWMA, PWMB and MEAS look ok (on the first glance) on my scope.
29 instructions at this moment..

PS: the rundown result with the below code will be calculated (my current understanding, please confirm, my math gets rusty):

Result  =  3 - 2*RDN + RDNP

where RDN and RDNP are the results returned by the PIO from the rundown.

Edit: small fix

Code: [Select]
.program ms
; MEAS PWMB PWMA signals in "set pins" with 4+2+1 weights

; don't forget to enable auto push
start:
    set pins, (0+0)                     ; switch all off (not required perhaps)
    mov X, !NULL                        ; set X to 0xFFFFFFFF
    out Y, 32                           ; read the number of desired counts
    irq 0                               ; first auxADC residue reading
    out NULL, 32                        ; stall until DMA finished reading the ADC

beginning:
    set pins, (4+1)                     ; MEAS=1
    jmp pin pwmhigh     
    set pins, (4+2)      [31]           ; was 15
    jmp Y-- beginning    [29]           ; was 13
    set pins, (0+2)                     ; MEAS=0
    jmp finish         

pwmhigh:
    jmp X-- dummy        [31]           ; was 15
dummy:
    nop                  [27]           ; was 11
    set pins, (4+2)     
    jmp Y-- beginning   
    set pins, (0+2)                     ; MEAS=0
    jmp finish

finish:

   in X, 32                             ; send X to FIFO (runup-counts), ref to neg, input off   

; rundown
   mov X, !NULL                         ; set X to 0xFFFFFFFF
   
count_neg:   
   jmp pin end_neg     
   jmp X-- count_neg                    ; count, jump to close the loop
   
end_neg:
   in X, 32              [2]            ; send X to FIFO (counts for neg ref.), some delay for minimum pulse length for settling

   set pins, (0+1)
count_pos:   
   jmp X-- cont                         ; count, no real jump
cont:
   jmp pin count_pos   

count_end:
   set pins, (0+0)                      ; turn switches off
   in X, 32                             ; send X to FIFO (counts for neg+pos ref.)

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

% c-sdk {

// Helper function (for use in C program) to initialize this PIO program
void ms_program_init(PIO pio, uint sm, uint offset, uint pin, uint input, float div, uint pin_MEAS) {

    // Sets up state machine and wrap target. This function is automatically
    pio_sm_config c = ms_program_get_default_config(offset);
   
    // Allow PIO to control GPIO pin (as output)
    pio_gpio_init(pio, pin);
    pio_gpio_init(pio, pin+1);
    pio_gpio_init(pio, pin_MEAS);     
   
    // set the pin for jump if pin high instruction
    sm_config_set_jmp_pin(&c, input);

    // Connect pin to SET pin (control with 'set' instruction)
    sm_config_set_set_pins(&c, pin, 3);
   
    // Set the pin direction to output (in PIO)
    pio_sm_set_consecutive_pindirs(pio, sm, pin, 2, true);      // 2 pins for PWM high and low
    pio_sm_set_consecutive_pindirs(pio, sm, pin_MEAS, 1, true); // 1 pin for MEAS pin

    // Set auto push to ISR
    sm_config_set_in_shift(&c, false, true, 32);
    sm_config_set_out_shift(&c, false, true, 32);
   
    // Set the clock divider for the state machine
    sm_config_set_clkdiv(&c, div);

    // Load configuration and jump to start of the program
    pio_sm_init(pio, sm, offset, &c);
}

%}

And the reading of the additional rundown results off the PIO's FIFO is easy (and it works):

Code: [Select]
void get_counts(PIO pio, uint sm , uint32_t countNum){
    pio_sm_put_blocking(pio, sm, countNum - 1);
    counts = ~pio_sm_get_blocking(pio, sm);     // MS runup count
    RDN = ~pio_sm_get_blocking(pio, sm);     // rundown negative charge
    RDNP = ~pio_sm_get_blocking(pio, sm);     // rundown negative+positive charge
}

« Last Edit: April 26, 2024, 06:28:49 pm by iMo »
 

Offline iMo

  • Super Contributor
  • ***
  • Posts: 4797
  • Country: pm
  • It's important to try new things..
Re: (Yet Another) DIY Multislope ADC
« Reply #92 on: April 25, 2024, 09:48:07 pm »
..The positive part is not even fixed, it can still vary a littlel (like +-1 cout) from noise and comparator hysteresis.

How do you handle the situation where ie. the positive part jitters +/-1 count?
Especially when doing post-auxADC measurement?

 

Online Kleinstein

  • Super Contributor
  • ***
  • Posts: 14233
  • Country: de
Re: (Yet Another) DIY Multislope ADC
« Reply #93 on: April 26, 2024, 06:32:00 am »
Both the negative and positive ref. counts are included in the result. This applies to both cases with the positive and negative charge to start with. So not special handling needed for cases when the short pulse at the end can have slightly different length.

The problem is not the cases with a short positive or short negative pulse . There is anyway also the case near zero resudual charge when both pulses are short.

The slight complication with a rundown come from a not perfect balance between the positive and negative reference. For the run-up part either the positive or negative reference is active. So the relevant scale factor is the difference between the 2 run-up step cases and thus the difference (including the sign) positive an negative reference currents. For the rundown part there are 3 possile states with positive, negative or no active reference. One can write the positive/negative ref. as:   +-0.5 * (pos-neg) + 0.5 (pos+neg) . The main part is still from the difference, like in the run-up, but there is an additional correction term from the sum of the references. With ideal symmetry this would be zero, but the circuit is usually not ideal and thus the extra small correction term with the sum of the reference currents. Ideally one would measure it in an extra calibration procedure (could be only once at the initial calibration) and include the correction term. The alternative would be highly accurate resistors (e.g. 0.05% range).

The   - 2*RDN + RDNP   from is for perfect symmetry. With the correction for possible asymmetry there is an additional small term proportional to RDNP. The post aux_adc would than add another term for additional resolution with a separate cal factor.
 

Offline iMo

  • Super Contributor
  • ***
  • Posts: 4797
  • Country: pm
  • It's important to try new things..
Re: (Yet Another) DIY Multislope ADC
« Reply #94 on: April 26, 2024, 07:34:36 am »
Yep, I've made an excel sheet to see the stuff in more detail, based on the paper linked in this thread, so I may play with the values (version 0).
The runup phase could have, say, X mV (or less) resolution, the rundown (in this design), say XX uVolts.
Then the auxADC on top of it - I have no math yet how to incorporate it into the end result, so as you indicate it would be matter of a calibration.. Still thinking how to formalize the rundown uncertainty and auxADC such it fits together smoothly..

PS: replaced the table because of an error, RrefP,N=Rin
« Last Edit: April 26, 2024, 03:32:35 pm by iMo »
 
The following users thanked this post: ch_scr

Online Kleinstein

  • Super Contributor
  • ***
  • Posts: 14233
  • Country: de
Re: (Yet Another) DIY Multislope ADC
« Reply #95 on: April 26, 2024, 09:15:25 am »
It is not a good idea to have different resistors for the input and reference currents. To get compensation of the switch resistance TC they should be the same.
Instead of a smaller resistor for the references a higher voltage (e.g. 14 V = 2 x raw reference) is the better way.

The times for RDN and RDNP should not get down all the way to zero. It would be more like 4 or 5 cylces as a minimum to allow for settling. For the result a constant added part is not important as one will subtract a zero reading anyway.
For the uncertainty the contributions from the parts (run-up, rundown difference of reference, rundown sum of reference and the residual ADC) is the relevant factor. With 1 PLC (20ms) the runup step are some 1/2000 for the full scale. With longer integration even more comes from the run-up. The run-down makes up some 2 run-up steps and in the current configuration some 120 cycles, the residual charge ADC is for 1 of the rundown steps or some 10 ppm of the FS.
 

Offline iMo

  • Super Contributor
  • ***
  • Posts: 4797
  • Country: pm
  • It's important to try new things..
Re: (Yet Another) DIY Multislope ADC
« Reply #96 on: April 26, 2024, 09:29:23 am »
The numbers in the table are just examples, I will put the excel table here when it settles. Edit: Moreover there is an error in the table, I calculated with Vref/2 values..

In your rundown's code above there are now 4+3 SM clocks for settling the NEG and 4 SM clocks for settling of POS. Could be stretched further on as one would need..

The runup timing could be modded easily by playing with the clock counts as well, I have now 4+60 SM clocks (1/16 ratio) and it just works.
Code: [Select]
;  60 to 4 SM clocks modulation (60+4=64 clocks)
..
beginning:
    set pins, (4+1)      [2]            ;
    jmp pin pwmhigh     
    set pins, (4+2)      [29]           ;
    jmp Y-- beginning    [29]           ;
    set pins, (0+2)
    jmp finish         
   
pwmhigh:
    jmp X-- dummy        [29]           ;
dummy:
    nop                  [25]           ;
    set pins, (4+2)      [2]            ;
    jmp Y-- beginning   
    set pins, (0+2)     
    jmp finish

finish:
..
« Last Edit: April 26, 2024, 10:56:06 am by iMo »
 

Offline NNNITopic starter

  • Contributor
  • Posts: 47
  • Country: de
    • YouTube channel
Re: (Yet Another) DIY Multislope ADC
« Reply #97 on: April 26, 2024, 12:24:17 pm »
iMo, once again, thanks for your work on the code. I never really considered using set pins for everything (both reference switches and input switch), this enables use of all delay bits for up to 32 cycles and ultimately saves much needed program space.

I am honestly not convinced about additional rundown when a residue ADC is already present. Based on my naive assumptions, if runup gives me roughly 12 bits of resolution and the residue ADC is also 12 bits, 20 bits (roughly 6.5 digits) should be possible. That way, only one constant would need to be calibrated to match runup and residue ADC readings.
 

Offline iMo

  • Super Contributor
  • ***
  • Posts: 4797
  • Country: pm
  • It's important to try new things..
Re: (Yet Another) DIY Multislope ADC
« Reply #98 on: April 26, 2024, 01:34:35 pm »
@NNNI: I've been interested in a deeper understanding of pros and cons of the rundown+auxADC alchemy as well, therefore my playing with the code and tables.. :)

Your hw is ready for the experiment with that combo, so you may try. I think the key message here is the auxADC is of less "quality" than the rundown process, therefore anything which would "de-load" the auxADC helps. You get rather small voltage at the integrator's output after the rundown, so the auxADC will handle much smaller input voltage range.

My main concern are the various coefficients you have to get somehow and apply "accordingly" to all those elements such you get a result..

But we have here people with hands-on experience, so let us learn from them..
« Last Edit: April 26, 2024, 01:43:21 pm by iMo »
 

Online Kleinstein

  • Super Contributor
  • ***
  • Posts: 14233
  • Country: de
Re: (Yet Another) DIY Multislope ADC
« Reply #99 on: April 26, 2024, 02:19:32 pm »
The main scale factor for the rundown is still the same as the runup. So ideally just the number of clock cycles per run-up set. It's only small corrections from asymmetry and settling effects during runup that may apply. Especially the correction for settling may not be needed unless the modulation is really fast (I don't need it at 8 digit resolution). The way with rundown may have 1 or maybe 2 correction constants, while the resudual ADC directly needs a pretty stable auxiliary ADC and a more critical cal factor there. Getting full 12 bits from the residue is pushing it: there is extra noise from the 2nd conversion and the gain factor and integrator capacitance have limited stability. After rundown the auxiliary ADC is something like 30 times less critical.

The rundown part is usually quite stable, as it uses the same reference as the runup.

For just 6.5. digits (with 1 or 10 PLC) just the resudue ADC can be OK. When aiming for more (especially high resolution already with short integration like 1 ms) the extra resolution from the rundown can really help. Getting more resolution from faster modulation is challanging on the integrator.

A downside with the extra rundown is a bit of extra time needed and also more code, which may be an issue with the limited code space for PIO. One may want a bit slower modulation or at least longer minimum pulse lengths to avoid the settling effect - for the resolution the fast runup is not longer needed.
 

Offline iMo

  • Super Contributor
  • ***
  • Posts: 4797
  • Country: pm
  • It's important to try new things..
Re: (Yet Another) DIY Multislope ADC
« Reply #100 on: April 26, 2024, 02:27:07 pm »
I've updated above table, there are RDN and RDP "fixed" clocks (5 as an example), and the zero values returned by RDN and RDP (an example) to see the runup values and diffs, where the RDP always returns at least "1" (we make the decrement before the comparator check).

Also my understanding is the rundown process above returns max 31n+1p (or 0n+30p) "net" counts, where one count == 2 SM clocks (thus rundown_resolution = runup_resolution/60 ).
« Last Edit: April 26, 2024, 03:40:30 pm by iMo »
 

Offline iMo

  • Super Contributor
  • ***
  • Posts: 4797
  • Country: pm
  • It's important to try new things..
Re: (Yet Another) DIY Multislope ADC
« Reply #101 on: April 27, 2024, 07:34:05 am »
Here is the excel table you may play with v1.0.
If you may find an issue pls do report.. :)

PS: the formula used:

Code: [Select]

Vin = (Vref * Rin / Rref) * (PWMcharge * (2 * RUPN - MS_N) + 2 * ( 2 * RDN - RDNP + 1)

          + RDNfix - RDPfix) / (PWMperiod * MS_N)


Update: v1.1 with fixed PWM clocks input
Update: v1.2 with fixed rundown calculation
Update: v1.3 with fixed rundown calculation - the RDPfix and RDNfix are single SM clock values, RDP and RDN are 2 SM clocks counter values
Update: v1.4 fix - everything shall be related to 56 SM clocks of charge (PWM_charge)..
« Last Edit: April 28, 2024, 12:13:56 pm by iMo »
 
The following users thanked this post: ch_scr

Online Kleinstein

  • Super Contributor
  • ***
  • Posts: 14233
  • Country: de
Re: (Yet Another) DIY Multislope ADC
« Reply #102 on: April 27, 2024, 08:47:04 am »
The run-up modulation with a 4/60 or 60/4 modulation has a usefull part of 60-4 = 56 cycles that are actually modulated. It is not just the 4 cycles that are effectively lost, but also the 4 the other polarity.
Depending on the integrator hardware 4 cycles (500 ns) for the shortest pulses and settling looks about right.
This gives the residual charge a range of about +-60 cycles range. depending on the delay between reading the comparator and the start of the feedback the range may get a little larger than just 1 feedback step. This way the run-down part could get a little larger than just -31 to + 30 counts. The range is more approximate than accurately calculted through.

A big question is how good the jitter is and if one needs / wants external synchronization to a more stable clock. Chances are the clock from the RP pico is not good enough and would at least need an external oscillator. It is not so much jitter, modulation of the crystal frequency depending on how neighboring pins are set or how much current is drawn. At the very least the pins for the ref. modulation should be away from the clock.
 
The following users thanked this post: iMo

Offline iMo

  • Super Contributor
  • ***
  • Posts: 4797
  • Country: pm
  • It's important to try new things..
Re: (Yet Another) DIY Multislope ADC
« Reply #103 on: April 28, 2024, 12:11:46 pm »
Updated to a perhaps the final version, where I returned to the traditional formula, which works properly only when the rundown charges are related to the "PWM charge" (56 in our case above).

The rundown range is +/- (0..27) counters diff counts (that is 56 SM clocks, also mind there are the RDN and RDNP inputs now as per the PIO source). The rundown now returns "reasonable" values, imho, which fit the both resolutions "smoothly".

For example the above runup resolution is 9800uV and the rundown resolution 175uV in 56 steps.

Still the question is how to handle the +/-1 noise in the rundown results and the incorporation of the noisy auxADC results..
 
« Last Edit: April 28, 2024, 12:26:34 pm by iMo »
 

Offline NNNITopic starter

  • Contributor
  • Posts: 47
  • Country: de
    • YouTube channel
Re: (Yet Another) DIY Multislope ADC
« Reply #104 on: April 28, 2024, 03:31:08 pm »
I finally took the time to read through all of the messages posted and process them properly.

I think I finally see some merit in removing as much charge from the integrator as the clock resolution will allow. As per the Landsberg rundown scheme, if I use the same clock to carry out rundown as I use for runup, the rundown counts can basically just be added to the runup counts. This eliminates the need for more constants that would need to be calibrated somehow. The effects of comparator hysteresis can be removed to a large extent by using some kind of zero-crossing slope amplifier, similar to the one described by Jim Williams in National Semiconductor App Note 260. This way, we don't need to add a certain amount of clock cycles' worth of charge into the integrator to compensate for comparator hysteresis. The board I designed has a footprint for such a slope amplifier, but I removed it since it had some issues. I will have to experiment with it some more. The residue ADC will have to digitize a much smaller integration range, I guess calculating that range mathematically and figuring out gain such that the small amount of charge left in the integrator spans the residue ADC's range will be most beneficial.

Of course, the latter part depends on the integrator starting and ending within that specific limited range. Dithering might necessitate a larger voltage range on the residue ADC. I will have to play around with my board to see what kind of numbers I get.

Regarding jitter, the numbers from a crude test performed by a friend indicate around 50ps RMS jitter, measured between successive rising edges of a GPIO toggling at 20MHz (done using PIO) with a 400MHz overclock. I am not sure how much of this comes from the crystal and how much from the PLL, and if a better crystal will make a difference. More (proper!) measurements will have to be made.
 

Online Kleinstein

  • Super Contributor
  • ***
  • Posts: 14233
  • Country: de
Re: (Yet Another) DIY Multislope ADC
« Reply #105 on: April 28, 2024, 04:02:19 pm »
The crystal clock jitter is usually on the order of 1 ps RMS. So the measured 50 ps are most likely mostly from the PLL.  This number also makes sense - it is about what the STM32G071 datasheet gives for a different µC with internal PLL. Jitter is usually not 100% white phase noise, but may have some extra lower frequency component. So when the clock is divided down (even with an ideal divider) the period jitter can go up. For the mudulation patter (some 5-20µs period) the effective noise could be a littler higher than the period jittter.

The noise added from jitter is about RMS jitter divided by the integration time times the reference strenght times the square root of the number of ref. switching events. As a number example maybe 50 ps / 20 ms * 28 V * sqrt(4000) = 4.4 µV rms.

50 ps jitter would add a noticeable noise source to the ADC, especially when using relatively fast modulation. It could still be OK for the 6-7 digit range. For lower noise one would likely need external synchronization directly to a stable clock. This could bring the jitter down to the 1-3 ps range.

 
The following users thanked this post: ch_scr, NNNI

Offline NNNITopic starter

  • Contributor
  • Posts: 47
  • Country: de
    • YouTube channel
Re: (Yet Another) DIY Multislope ADC
« Reply #106 on: April 28, 2024, 04:26:09 pm »
Thanks for the example calculation, it was very insightful.

There is always the option of running the RP2040 without a PLL from an external 48MHz clock (which would also work out in terms of timing, 48MHz is exactly half of the 96MHz I chose for the previous code). I am not sure if this would yield much improvement.

Would I be right in assuming that the faster a logic IC is meant to be clocked, the lower the jitter? For example, the SN74LVTH273 [1] can be clocked at up to 150MHz. The latch can be clocked from the same oscillator that is feeding the RP2040, that might help with synchronization issues.

[1]: https://www.ti.com/lit/ds/symlink/sn74lvth273-ep.pdf
 

Online Kleinstein

  • Super Contributor
  • ***
  • Posts: 14233
  • Country: de
Re: (Yet Another) DIY Multislope ADC
« Reply #107 on: April 28, 2024, 04:42:52 pm »
The faster locic chip usually add less jitter, though it is not a direct link. I had a hard time finding some jitter specs for the logic chips. An an analog devices application note (AN 501) there are a few numbers:
74HCT... ~ 2.2 ps
74ACT... ~ 1 ps
74LS...      5 ps
The 74LVTH and similar modern CMOS series are likely more like the ACT.

Depending on the code to run, one may not need that much clock. After all the RP2040 has 2 cores. So not need to get close to the 50 MHz max for an external clock.
In my ADC version I use only 8 MHz, though I see it getting tight in some places to do the math. The same clock for the sync and RP2040 is definitely a good idea. If the PIO runs slower one would still want a phase adjust step and than could still use the PLL for the µC clock.
A direct USB link and thus need for the 48 MHz is not really there, as one usually wants an isolation layer to USB.
 

Offline iMo

  • Super Contributor
  • ***
  • Posts: 4797
  • Country: pm
  • It's important to try new things..
Re: (Yet Another) DIY Multislope ADC
« Reply #108 on: April 28, 2024, 05:53:21 pm »
..In my ADC version I use only 8 MHz, though I see it getting tight in some places to do the math. The same clock for the sync and RP2040 is definitely a good idea. If the PIO runs slower one would still want a phase adjust step and than could still use the PLL for the µC clock.
A direct USB link and thus need for the 48 MHz is not really there, as one usually wants an isolation layer to USB.

Why do you need that perfect sync at the clock level between 2040 and PIO? The 2040 and PIO have nothing common with the clocking, there is no clock domain crossing with missing sync. Those are fully independent, because they communicate via FIFO/interrupts (this handles the domain crossing), a kind of async communication.
The PIO is a bunch of cmos logic stuff, with perhaps 1ps or less jitter, which has no "direct signal lines" to the CPU, except the clock line.
The CPU and PIO share the clock in 2040, but there is no need on phasing or whatever. The design here is different to your AVR/ARM designs where your peripheries and core CPU were somehow phase depended, imho.


« Last Edit: April 28, 2024, 06:07:53 pm by iMo »
 

Online Kleinstein

  • Super Contributor
  • ***
  • Posts: 14233
  • Country: de
Re: (Yet Another) DIY Multislope ADC
« Reply #109 on: April 28, 2024, 08:18:47 pm »
There is no need for a perfect sync betwen the CPU and PIO part. Usually this is given as the PIO clock is from a divider. Only the possible fractional divider could cause trouble.

The sync problem would appear, when the CPU runs from the PLL and than external sync FF are used to directly synchronize to an external clock. This case is triky and if possible I would avoid it because of the complications with the phase, even if the PIO clock would be the same as the PLL input clock.

The more realistic case is an external clock (e.g. 20 MHz range) to directly run the CPUs. The PIO clock could even be a bit lower to get the delays without extra code.
Chances are one can skip an external sync step, though there is possibly a tiny bit of delay modulation from the µC internal state that could lead to a little INL.
If needed / wanted an external sync with 2 flip flops (the input path is not that critical and could be direct) is not that complicated if there is no PLL involved.
 

Offline iMo

  • Super Contributor
  • ***
  • Posts: 4797
  • Country: pm
  • It's important to try new things..
Re: (Yet Another) DIY Multislope ADC
« Reply #110 on: April 28, 2024, 09:04:07 pm »
NNNI may test that easily (including the new rundown) while running off the stock 12MHz crystal against the PLL version. A stable canned XO/TCXO would be even better. The 48MHz is needed, however, as you want to upload the binary to the 2040 easily, and you will do it many times, sure.

On the other hand I would be much more concerned about the noise around the comparator and auxADC.. That introduces errors and I would be happy to see some real data coming off the above code, such we may play with the math. Perhaps NNNI finds some free time for running it on his pcb, its just a copy/paste exercise..
 

Online Kleinstein

  • Super Contributor
  • ***
  • Posts: 14233
  • Country: de
Re: (Yet Another) DIY Multislope ADC
« Reply #111 on: April 28, 2024, 09:19:45 pm »
To make use of the extra resolution gained from the rundown part one would need additional gain for the residue ADC. Without extra gain there is not much gained.

The comparator noise  should not be an issue - it only increases the range that the residue ADC has to cover a little.
For the aux ADC it is often more the amplifier than the actual ADC noise. With less resolution needed from the aux ADC it would be less than before.
Including the rundown part makes the aux ADC less critical (get some 5 bits from the rundown instead) and even the internal ADC may than be good enough.

Wanting the 12 MHz for an easy code download is a good point.
 

Offline NNNITopic starter

  • Contributor
  • Posts: 47
  • Country: de
    • YouTube channel
Re: (Yet Another) DIY Multislope ADC
« Reply #112 on: April 28, 2024, 09:30:40 pm »
I was just about to bring up the point about being able to upload code via USB. It is very convenient and fast. However, programming via the SWD pins (using a Raspberry Pi debugger, for example) is another alternative. I am not sure how much SWD programming is dependent on system clock.

I am honestly not sure when I will be getting back to the project. I left it in a rather messy state, so getting everything running and familiarizing myself with the code diminddl and I worked on nearly a year ago will take some time, plus I have to finish testing my own ideas first. The project files are available, so it should be possible to get your own set of boards for experimentation, or replicate the core circuit (it's quite simple) on a breadboard. I understand your eagerness for the results, but all I ask for is a little patience till I can get everything sorted on my side. ;D
 

Online PCB.Wiz

  • Super Contributor
  • ***
  • Posts: 1555
  • Country: au
Re: (Yet Another) DIY Multislope ADC
« Reply #113 on: April 28, 2024, 10:48:29 pm »
NNNI may test that easily (including the new rundown) while running off the stock 12MHz crystal against the PLL version. A stable canned XO/TCXO would be even better.
An external Osc is certainly easy to try.
TCXO's need care, as some use digital corrections that give small jumps in frequency as the temperature varies.
Some vendors now call their better TCXOs analog compensated - eg
https://ecsxtal.com/news-resources/what-are-the-benefits-of-using-analog-compensated-tcxos/

I'm thinking the ideal is an oscillator that is (very) stable over the integration time.
That means long term drift is less important, & it is best to focus to avoid effects like micro-jumps or other disturbances.
The close-in phase noise is looking like the best indicator of that.

A bit of thermal mass around the oscillator can help reduce temperature slope effects, and a local low noise regulator can isolate supply variations.


The 48MHz is needed, however, as you want to upload the binary to the 2040 easily, and you will do it many times, sure.

You just need to be able to generate 48MHz for the USB, so more clock choices exist.
I've not found a very low phase noise oscillator at 48MHz yet, tho NDK say they can cover 20-50MHz in their NZ2520SDA family. Just needs some MOQ  8)

Addit : chip1stop do show a NZ2520SDA 48MHz order code, so I've asked the MOQ on that. (they also have codes for 35MHz and 54MHz, not indicated by NDK ?)
« Last Edit: April 28, 2024, 11:31:46 pm by PCB.Wiz »
 

Offline iMo

  • Super Contributor
  • ***
  • Posts: 4797
  • Country: pm
  • It's important to try new things..
Re: (Yet Another) DIY Multislope ADC
« Reply #114 on: April 29, 2024, 06:34:41 am »
..The project files are available, so it should be possible to get your own set of boards for experimentation, or replicate the core circuit (it's quite simple) on a breadboard..

Yep, the analog part of the design is an another story which we have not elaborated yet :)
My basic motivation has been to have a look at the 2040/PIO and its applicability. Of course it could be done by a stm32xxx (here we lack the PIO) or an fpga+MCU (here the complexity is higher) as well.
Hopefully rPi company will come with the rp2041 soon - with the fixed ADC, and with 4xPIO with 256 instructions each :)

 
The following users thanked this post: PCB.Wiz

Online Kleinstein

  • Super Contributor
  • ***
  • Posts: 14233
  • Country: de
Re: (Yet Another) DIY Multislope ADC
« Reply #115 on: April 29, 2024, 07:46:23 am »
There is no need for a super stable clock. The point is jitter over a time frame of some 10 µs. The switches and an optional buffer to improve the isolation would add a few ps of jitter anyway. So a standard crystal oscillator should be good enough.  The crystal directly at the RP2040 as for the RP-pico could have an issue with the internal state effecting the clock - I had this issue with the AVR and this caused quite some INL error (e.g. 10 ppm range). Chances are 12 MHz directly with no PLL could be fast enough for the ADC, though this would not allow to use the USB while using the ADC.
 

Offline NNNITopic starter

  • Contributor
  • Posts: 47
  • Country: de
    • YouTube channel
Re: (Yet Another) DIY Multislope ADC
« Reply #116 on: April 29, 2024, 01:07:32 pm »
iMo, I got a chance to talk to Eben Upton at Maker Faire Hannover 2023. He mentioned that the instruction memory for PIO was closely coupled to the architecture, so more memory is apparently not the easiest to implement. He did hint at using out exec to overcome this limitation, but that comes with its own challenges.

I was looking at suitable crystals, and apparently a 48MHz version of the crystal [1] Jaromir used in the ADC for his NVM project [2] exists. I was not able to find jitter specs in the datasheet. But as Kleinstein says, a 'regular' oscillator will probably suffice, since a latch like the '273 will add its own jitter. The 48MHz version [3] of the temperature compensated crystal series PCB.Wiz recommended is available at a reasonable price in single quantities from Mouser.

Once I have the issues with the code sorted out, I think it would make for an interesting comparison to see how well the latched version performs.

[1]: https://www.mouser.com/datasheet/2/137/SG5032CAN_en-961596.pdf
[2]: https://github.com/jaromir-sukuba/nvm/blob/main/hardware/Schematics_pdf/HOMER/rnvm_homer.pdf
[3]: https://www.mouser.com/datasheet/2/122/ECS_3225MVQ-1825332.pdf
 

Online Kleinstein

  • Super Contributor
  • ***
  • Posts: 14233
  • Country: de
Re: (Yet Another) DIY Multislope ADC
« Reply #117 on: April 29, 2024, 03:57:39 pm »
I would not go for just a crystal, as the frequency can be effected by the µC and this can cause nasty INL problems.
There are relatively cheap boxed oscillators that can do the job (some 1 ps jitter specs seem to common).
The question is if one needs external latches / flip flops for an extra sync. step. The extra external sync step may reduce the jitter a little and reduce possible delay modulations at the µC, but it also adds power consumption and possibly EMI problems. There is a good chance that one could skip it.
With an external sync one would likely use a relatively low clock (like 12 MHz), which should make the USB use easy.
Without an external sync one may opt for a faster clock (maybe 48 MHz if one wants USB while the ADC is active).
For the processing power already 12 MHz should be sufficient. A DMM would anyway have a 2nd µC at the output / interface side.
 

Offline iMo

  • Super Contributor
  • ***
  • Posts: 4797
  • Country: pm
  • It's important to try new things..
Re: (Yet Another) DIY Multislope ADC
« Reply #118 on: April 30, 2024, 07:12:57 am »
I would not go for just a crystal, as the frequency can be effected by the µC and this can cause nasty INL problems.
There are relatively cheap boxed oscillators that can do the job (some 1 ps jitter specs seem to common).
The question is if one needs external latches / flip flops for an extra sync. step. The extra external sync step may reduce the jitter a little and reduce possible delay modulations at the µC, but it also adds power consumption and possibly EMI problems. There is a good chance that one could skip it.
With an external sync one would likely use a relatively low clock (like 12 MHz), which should make the USB use easy.
Without an external sync one may opt for a faster clock (maybe 48 MHz if one wants USB while the ADC is active).
For the processing power already 12 MHz should be sufficient. A DMM would anyway have a 2nd µC at the output / interface side.

In your latest MS ADC schematics here (the AVR based one ) you are passing the 2 channel selection signals of the 4053 (VrefP and VrefN switches) via two FFs (1x 74AC74), while the two FFs are clocked directly from the canned xtal oscillator box. That could be added into the design, and bypassed when not needed.
« Last Edit: April 30, 2024, 07:20:29 am by iMo »
 

Online Kleinstein

  • Super Contributor
  • ***
  • Posts: 14233
  • Country: de
Re: (Yet Another) DIY Multislope ADC
« Reply #119 on: April 30, 2024, 10:56:13 am »
The extra flip flops synchronize the ref. signals directly to the clock. It is not so much for the jitter, but more for small INL effects when the µC state effects the delay. For the AVR this effect is visible though still not that much of an issue ( < 0.1 ppm FS for the INL). I have tried both with and without the extra FF with not much difference.
 
The following users thanked this post: PCB.Wiz


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf