Showing posts with label analog discovery. Show all posts
Showing posts with label analog discovery. Show all posts

Monday, September 29, 2025

0

Exploring Automation Possibilities with the ADALM1K Learning Kit

Summary:

During my search for a low cost electronics learning module, I came accross the ADALM1K which has interesting features for the price point (approx. 70$). It incorporates a source measure unit (SMU), an oscilloscope and a function generator. On top of that the hardware and software is open-source which is a learning experience in itself to undestand how the kit works.

My goal was first to test how the kit works overall. Once I had some confidence in its usage functions, I dived deeper into its evaluation / application software to look for automation oppurtinites with Python, where one could automate custom workflows for measurement and learning purposes.

I was able to integrate the ADALM1K with my Raspberry Pi setup and automate its functionality using the provided libsmu/pysmu Python package from Analog. I ended up creating a small Python library (pytest-analog) around libsmu so I could write some automated tested for my projects usning the ADALM1K

As an example, I created automated test cases via Python to measure the power consumption of  a DUT (ESP32 Dev board). This could be extended to create more complex test cases for your system under test using very low cost equipment such as the ADALM1K

Hardware: 

The ADALM1K features two analog channels that support source and measure functionality for different waveforms in voltage or current mode. To offer this functionality, it uses a number of building blocks to take the fixed supply and digital interface of USB and offer voltage and current operation.

The main hardware sepcs are as follows:

  • Two channels supporting measure and source function simultaneously: voltage (0 to 5V) or current output (- 200 to +200mA)
  • Two fixed power supplies (2.5V and 5V) supprting up to 200 mA current draw
  • 16-bit (0.05%) basic measure accuracy with 4 digit resolution
  • Four digital signals (GPIOs 3.3V CMOS)

ADALM1K Block diagram per SMU Channel (wiki.analog.com)

As per the above the diagram, an analog channel on the ADALM1K combines a function generator and an oscilliscope instrument on the same pin. In Rev F of the board, the analog ouput and input functions could be seperated with the two provided addiotnal split pins such that the oscillscope function is brought out along with 1 MΩ from the function generator function. Therefore, each analog channel could be configured to one of the following options:

  • Source Voltage and Measure Current (with / wihtout Split IOs)
  • Source Current and Measure Voltage (with / wihtout Split IOs)
  • High Impedance (with / wihtout Split IOs)

If you would like to learn more about the ADALM1K hardware and its design, the following resources are good to read through:

ADALM1000 Board Upside View


 
ADALM1000 Board Underside View

Software:

The software landscape of the ADALM1K comprises the device firmware and the host software which can run on different platforms (Winodws / Linx / OS-X).

The ADALM1K firmware runs on an Atmel based microcontroller. The host software includes a C++ library (libsmu) containing the abstractions for streaming data to and from ADALM1K via USB. In addition, the Pixelpulse 2 and ALICE GUI-based tools are available to control the ADALM1K and make measurements with it. 

Testing with Analog Discovery:

In order to test the opertion of the ADALM1K via the provided GUI software Pixelpulse 2 and ALICE, I did some basic checks to test the ADALM1K analog and digital inputs/outptus via my Analog Discovery 3 (another great electronics learning tool). In these tests, I connected the two instruments to my PC and started their host softwares simultaneously to feed inputs and read outputs.

Test 1: Checking analog outputs of the ADALM1K via the Analog Discovery scope channels: 

As shown in the image below, I connected the ADALM1K source channels A, B to the Analog Discovery scope channels 1, 2. Then using ALICE software I configured an output voltage on channels A, B and then read measured voltages on the scope channels via the WaveForms software of Analog Discovery 3. I configured channels A, B to output 3.6, 1.2 V. On the Analog Discovery, I read approximately similar values on channels 1, 2. There is a slight 200 mV deviations which also seem to occur when I set the ADALM1K to ouput 0 V. Therfore, the ADALM1K requires some calibration before doing any real testing.


 Test 2: Checking GPIOs state of the ADALM1K via the Analog Discovery digital channels:

In this test, I connected the ADALM1K GPIO pins (0-3) to the Analog Discovery Digital IOs (0-3). Using ALICE software, I have set the ADALM1K GPIOs to a defined high / low state and then checked if the same state is read on the Analog Discovery side using its Static IO instrument in the WaveForms software. I was able to confirm the GPIOs state (high for pins 0,1 and low for pins 2,3)

 

Integration with Raspberry Pi: 

My next step was to connect the ADALM1K to my Raspberry Pi and get it working using the libsmu library provided by Analog. I wanted the setup to be headless so I could simply login remotely to the Pi and then run Python scripts to run different workflows with ADALM1K (i.e. something like a remote testing station). On the hardware side, I could simply connect the ADALM1K to my Raspberry Pi 5 via USB. On the software side, I had to compile and install libsmu from source as there was no ready-to-use package for Raspbian OS platform. 
 
You can refer to the this github repo section for building and installing libsmu on a Linux / Windows based platform. After installing libsmu, a utility executable named:"smu" should be available and you could trigger it to check if the ADALM1K board can be detected. For example: running smu -l command to list available devices as show below.
 
 
 
In addition, I have installed pysmu which contains the Python bindings for libsmu to control ADALM1K via Python. To test the interaction via Python, I started an interactive Python session via Ipython and ran some commands to check if I could configure the ADALM1K and read data from it as shown below.
You can refer to pysmu_examples to get more familiar with it.
 
 

Python Wrapper and Test Automation: 

After integrating the ADALM1K with my Raspberry Pi setup and getting familiar with the libsmu / pysmu libraries, I decided to create a small python library (wrapper class) to ease the control of the instrument functions and also create pytest-fixtures for setting up / tear down of the instrument in an automated testing environment. The library is named pytest-analog and it also support the automation of the Analog Discovery instrument from Digilent.

To demonstrate the usage of ADALM1K with pytest-analog in automated testing context, I created a small python test case where the ADALM1K would measure the power consumption of an ESP32 microcontroller running different sketches.

Given the instrument source and measure capabilites, it can power the ESP32 with a given voltage and measure drawn current simulatenously.

The steps to create an automated test with the ADALM1K via pytest-analog are listed below:

  • Create an empty workspace folder (e.g pytest_analog_tmp) and navigate to it (In bash terminal):
    • mkdir pytest_analog_tmp && cd pytest_analog_tmp
  • Create a Python virtual environment to install pytest_analog and its dependencies in isolation:
    • python3 -m venv venv
    • . venv/bin/activate
    • python3 -m pip install --extra-index-url https://test.pypi.org/simple/ pytest-analog 
    • python3 -m pip install matplotlib 
  • Create an empty "pytest.ini" file to provide the ADALM1K configuration at the start of the test with the content below. 
The first couple of lines are pytest specific to configure its output options and logging format. The last two lines are used by the fixtures in pytest-analog to configure channels A, B output voltage. Channel A is used to power the ESP32 at its 3.3V supply pin.
[pytest]
# pytest options
addopts = -v --capture=tee-sys

# Filtering Warnings
filterwarnings =
    ignore::DeprecationWarning

# Logging Options
log_cli=true
log_level=INFO
log_format = %(asctime)s %(levelname)s %(message)s
log_date_format = %Y-%m-%d %H:%M:%S

# ADALM1000 Fixtures Options
# Voltage Source
adalm1k_ch_a_voltage = 3.30
adalm1k_ch_b_voltage = 0.00 
  • Create a test_esp32_current_consumption.py file with the content below: 
import numpy as np
import pytest
import time
import math
import logging
import matplotlib.pyplot as plt
from pytest_analog import ADALM1KWrapper, AnalogChannel
from datetime import datetime

def test_esp32_current_consumption(
adalm1k_voltage_source: ADALM1KWrapper
) -> None:

# 2000 samples collected at base rate 100 kHz with averaging every 1000 samples -> 20 seconds
MEASUREMENTS_COUNT = int(2000)
# Do some averaging over collected data
AVERAGE_RATE = int(1e3) # average every 1 / AVERAGE_RATE, Default sampling rate of ADALM1K is 100 kHz

samples = []
ch_a_avg_voltage = []
ch_a_avg_current = []

# Read incoming samples in a blocking fashion (timeout = -1)
for _ in range(MEASUREMENTS_COUNT):
samples.append(adalm1k_voltage_source.read_all(AVERAGE_RATE, -1))

# Average captured readings
for idx in range(MEASUREMENTS_COUNT):
# voltages in V
ch_a_voltage = [sample[0][0] for sample in samples[idx]]
# currents in mA
ch_a_current = [sample[0][1] * 1000 for sample in samples[idx]]

ch_a_avg_voltage.append(np.mean(ch_a_voltage))
ch_a_avg_current.append(np.mean(ch_a_current))

logging.info(f"Average current consumption: channel A: {np.mean(ch_a_avg_current):.3f} mA")
logging.info(f"Max current consumption: channel A: {np.max(ch_a_avg_current):.3f} mA")

# plot current profile
t = np.arange(0, MEASUREMENTS_COUNT) / (100e3 / AVERAGE_RATE) # Default sampling rate is 100 kHz
fig, ax = plt.subplots()
fig.suptitle(f"ESP32 Blinky current consumption", wrap=True)
fig.supxlabel("Time (s)")

ax.plot(t, ch_a_avg_current, color='red')
ax.set(ylabel= "CH_A I(mA)")
ax.margins()
ax.set_xlim([0, math.ceil(np.max(t))])
ax.grid(True, which='both')
ax.minorticks_on()

plt.savefig(f"I_consumption_esp32_blinky_{time.strftime(datetime.now().strftime('%H%M'))}.png")
  • Run the test using pytest: pytest test_esp32_current_consumption.py  which generates the following logs in the terminal.

Current consumption profile for ESP32 blinking an LED every 2 seconds


Current consumption profile for ESP32 going into deep sleep mode for 5 seconds then waking up shortly

After the test execution, a graph is generated with the measured current consumption profile during the test. The graphs above are for two different sketches running on the ESP32. 

The first one is a basic blinky sketch where one could certainly see an increase in current draw when the LED is on. The duration of those peaks match closely with the LED-On period as expected.

The second sketch showcases the ESP32 deep sleep mode for extreme power saving applications, where the device is consuming a couple of miliamps during sleep mode and then waking up shortly every 5 seconds.

IMPORTANT: The above results can be inaccurate and require verification with a professional equipment to compare how good the ADALM1K is in capturing power characterstics of a given DUT.


Saturday, August 2, 2025

0

pytest-analog a python plugin for electronics experiments and test automation

Introduction

pytest-analog is a python library / pytest plugin for simple experimentation with electronics and embedded systems.

It is also a great tool for low cost test automation of low power IOT devices.

The library provides an easy to use wrapping layer to perform mulitple measurement and testing workflows utilizing two multifunctional instruments:

Supported Workflows: 

  • Power measurements:

    • The ADALM1K two SMU channels (A, B), can power up your project and measure its power consumption simulatenously. the ADALM1K channels cuurent operation ranges from -200 to +200 mA. The voltage range operation is from 0 to 5 V 

    • The Analog Discovery Supplies channels (V+, V-) you can supply both positive and negative voltages with the range of (0.5 V to 5 V , -0.5 V to -5 V) . In the Analog Discovery 3, each supply raile can supply up to 800 mA

    •  Due to ADALM1K (2-quadrant) operation, its two SMU channels (A, B) could be used to source and sink currents ± 200 mA. This could particulaly be useful for testing batteries charge and discharge profiles and DC characterstics of a circuit

  • Analog Inputs / Outputs:

    • When configured in high impedance modes, ADALM1K analog channels (A, B) could be used to probe analog signals 

    • The Analog Discovery Supplies channels (V+, V-) you can supply both positive and negative voltages with the range of (0.5 V to 5 V , -0.5 V to -5 V) . In the Analog Discovery 3, each supply raile can supply up to 800 mA

    •  Due to ADALM1K (2-quadrant) operation, its two SMU channels (A, B) could be used to source and sink currents ± 200 mA. This could particularly be useful for testing batteries charge and discharge profiles and DC characteristics of a circuit

Example Setup with Raspberry Pi 5: 

To demonstrate a practical application of the pytest-analog plugin, I built a small test setup with the Raspberry Pi 5 acting as a low cost computer. 

Below is the list of used hardware and software components for reproducibility:

  • Hardware

  1. Raspberry Pi 5 Model as the test station mini PC 
  2. ADALM M1K Board as a mini power supply / source measure unit (SMU) 
  3. Analog Discovery 3 as a USB Oscilloscope, Waveform Generator, Logic Analyzer, and Variable Power Supply
  • Software 

    1.Raspbian OS: 12 (bookworm) 64 bit lightweight Linux distribution for ARM architecture

    2. Python: 3.11.2 Python interpreter which is shipped as part of Raspbian OS
    3. libsmu: 1.0.4 library and python bindings for ADALM1K SMU
    4. WaveForms: 3.23.4 GUI application for measurements with Analog Discovery devices
    5. Adept: 2.27.9  Runtime library for communication with Analog Discovery devices
    6. pytest-analog: 0.2.0  python library / pytest plugin for test automation with the above hardwae