Hi everyone,
I’m working on a project called Tolog-Alpha. It’s an experimental 3x3 grid of analog nonlinear oscillators (TL082-based) where I’m studying emergent synchronization (Kuramoto-like coupling).
Current Setup:
9 independent RC relaxation oscillators.
Coupling via a resistor network (planning to upgrade to digital pots MCP41010 for dynamic K adjustment).
Monitoring via Arduino Mega (9 analog inputs) + Python Dashboard.
The Challenge:
I’m hitting some walls with the sampling rate and phase extraction. I need to monitor all 9 channels simultaneously to detect phase waves and chimera states.
Does anyone have experience with optimizing analogRead() for 9 channels to keep the sampling consistent enough for Hilbert Transform analysis in Python?
Has anyone tried using digital potentiometers (SPI) to control coupling strength between oscillators in a grid like this?
I have the Python dashboard and simulations (100% success rate in model) ready, but moving to hardware is tricky. Any tips on reducing crosstalk between the channels or improving the phase resolution?
Thanks!
Patrik (Tolog Institute)
There is the first problem. The Mega has only one A/D converter that is shared (switched) between all analogue inputs. Common practice of all small single-core processors.
Impedance of an input signal must be kept below 10K Ohm, to limit cross-talk.
And then there is the limited sample rate of about 10kHz (default), which limits AC sampling to frequencies of 5KHz.
Leo..
Thank you for the useful feedback.
Yes, I am aware that the Arduino Mega uses a single ADC multiplexed across the analog inputs. For the current prototype I plan to run the oscillators at relatively low frequencies (around 50–150 Hz), so the effective sampling rate per channel should still be sufficient for phase estimation.
The goal of this setup is mainly to monitor phase relationships between oscillators rather than to capture the full waveform.
I will also make sure that the input impedance stays below about 10 kΩ or add buffering if necessary.
Thanks again for the technical advice.
You can do this by running the signal through a Exclusive OR gate.
Hi, @patriktolog
Welcome to the forum.
The other aspect of the multiplexed ADC is that it takes time for each acquisition of each selected input.
When you read say input 1, then read input 2, you have to wait for the value at the input of the ADC to get to that level because the ADC has a capacitor from input to gnd.
This stores the voltage and with 10K input impedance will not instantly change to the new value.
Have you done experiments with JUST ONE input to see what your frequency response is?
Remembering the response will decrease with added analog channels.
Tom....
![]()
+1
Make the signals digital by detecting their zero-crossings and then compare the digital signals. Like a PLL (Phas-locked-loop) circuit.
Then the following execution sequence is not valid?
int y1 = nalogRead(A0);
int y2 = analogRead(A1);
==>
Phase-locked loop?
Hi Tom,
Thank you for the explanation.
Yes, I understand the issue with the sample-and-hold capacitor when switching channels on the multiplexed ADC.
My plan is to start by testing the frequency response using a single oscillator input and then gradually increase the number of channels to see how the effective sampling rate and accuracy change.
The oscillators in the experiment will run at relatively low frequencies (around 50–150 Hz), so the timing constraints should hopefully remain manageable.
Thanks again for the helpful advice.
Thanks for the suggestion.
Converting the oscillator signals to digital using zero-crossing detection makes a lot of sense. That would simplify the measurement compared to sampling the analog waveforms with the ADC.
Using an XOR gate as a phase detector, similar to a PLL approach, is a very interesting idea. I will experiment with that method for comparing oscillator phases.
Thanks for the helpful advice.
Yes, that is currently the type of sequence I was considering.
I understand now that because the Arduino Mega ADC is multiplexed, switching channels can require a short settling time for the sample-and-hold capacitor.
Using a dummy read after switching channels sounds like a good approach to allow the input to stabilize before taking the actual measurement.
Thanks for pointing that out.
Because the int y = analogRead(A0) function carries out the following steps, then why should we take a dummy reading in between the channel switching for the stablization of the holding capacitor:?
1. Ananlog channel and Vref are selected,
2. Conversion clock is at its default value of 125 kHz,
3. Conversion command is used,
4. Waiting for the conversion to end, and then
5. 16-bit content (upper 6-it are always 0s) of the ADC registers is transferred to the user variable y.
Good question.
My understanding is that the ADC conversion itself waits for completion, but the issue occurs when switching between channels. The sample-and-hold capacitor inside the ADC may still contain charge from the previous channel, and if the input impedance is not very low it may take a short time to settle to the new voltage.
That is why some people recommend a dummy read after switching channels, especially when reading multiple analog inputs in sequence.
In my case I will also try to keep the source impedance below about 10 kΩ to minimize this effect.
Why are you worry about the source impedance? It is the voltage that is being measured by the ADC.
The source impedance matters because of the ADC’s internal sample-and-hold capacitor (C_{sh}). According to the ATmega328P/2560 datasheet, a source impedance higher than 10kΩ can prevent the capacitor from charging fully during the sampling interval, leading to inaccurate readings and ghosting between channels.
Since Tolog-Alpha relies on precise phase extraction, even a small error in the RC settling time would destroy the Hilbert Transform results. That's why I'm leaning towards the XOR-based digital approach—it bypasses the analog multiplexer's limitations entirely.
You have a lot of Python processing and dasboard updating for real time signals. Then why don't you explore the use of Arduino UNO Q (Fig-1) which will meet your all requiremts in one place/board ---
- real time signal acquisition under Zephyr RTOS driven 32-bit 160 MHz STM32U585 MCU
- processing of signal using Python programmed Linux driven 64-bit 2.0 GHz QBR2210 MPU
- Onboard WiFi to drive dashboard.
- 9 ADC channels requirements could be meet by putting an external ADS1115 ADC (4-channel) + UNO Q's 6-cannel.
Figure-1:
The Arduino UNO Q looks like a beast! Having a 2GHz MPU with Linux and 2GB RAM would certainly solve the bottleneck of Serial communication to a PC. Running the Python dashboard directly on the board via HDMI or WiFi is a tempting upgrade for the Tolog-Alpha V2.0.
However, for the current hardware validation, I'm sticking to the 'All-Analog Grid + XOR logic' to keep the phase dynamics as pure as possible. But once the 3x3 lattice is stable, the UNO Q with an external ADS1115 for high-res monitoring seems like the perfect path for a standalone research module in Sázava. Thanks for the tip!
Sorry! I thought that you have the MEGA for signal acquisition and then some other boards for processoing and networking . I am not aware about your Tolog-Alpha V2.0.
No need to apologize! Your suggestion for the UNO Q was actually spot on for the future scaling of the project.
Tolog-Alpha is currently in the 'proof-of-concept' hardware stage (V1.0), focusing on the raw analog interaction of the lattice. V2.0 will indeed move towards more integrated, high-performance processing—and that's where your tip about the STM32/Linux hybrid will be gold.
Stay tuned, the Sázava lab is just getting warmed up!
Where is it? Is it a Research Lab of a University or a Commercial Enterprise?



