Skip to content

Blog

My Recent Project: ActiveCpp

I am excited to share my recent project, ActiveCpp, which is now live on my website samiralavi.github.io/activecpp/main. ActiveCpp is a powerful and versatile C++ library that simplifies asynchronous programming and enables developers to create highly responsive applications.

Why ActiveCpp?

As a software developer, I have always been fascinated by the potential of asynchronous programming. However, I often found it challenging to write efficient and maintainable asynchronous code in C++. That's when I decided to create ActiveCpp. The original idea was in an abandoned repository lightful/syscpp, which helped me at the time a lot. Therefore I decided to revive this dead project and support it to further help the engineers like me develop event-driven systems in Modern C++ more efficiently.

ActiveCpp provides a set of intuitive and easy-to-use abstractions that make it effortless to write asynchronous code. It leverages the power of coroutines and event-driven programming to handle concurrency and improve the responsiveness of C++ applications.

Key Features

ActiveCpp offers several key features that make it a valuable tool for C++ developers:

1. Asynchronous Execution

With ActiveCpp, you can easily define and execute asynchronous tasks. By using coroutines, you can write code that appears synchronous but executes asynchronously, allowing your application to remain responsive.

2. Event-Driven Programming

ActiveCpp embraces the event-driven programming paradigm, allowing you to handle events and triggers efficiently. You can define event handlers and subscribe to events, making it easier to build reactive and event-based systems.

3. Task Scheduling

The library provides a flexible task scheduling mechanism that allows you to control the execution order and prioritize tasks. You can schedule tasks to run in parallel or sequentially, depending on your application's requirements.

4. Error Handling

ActiveCpp simplifies error handling in asynchronous code. It provides mechanisms to propagate and handle errors gracefully, making it easier to write robust and fault-tolerant applications.

Getting Started with ActiveCpp

To get started with ActiveCpp, head over to samiralavi.github.io/activecpp/main and explore the documentation and examples. You will find comprehensive guides, tutorials, and API references to help you understand and utilize the library effectively.

Conclusion

ActiveCpp is a game-changer for C++ developers who want to harness the power of asynchronous programming. With its intuitive abstractions and powerful features, it simplifies the process of writing responsive and efficient code. I invite you to check out the project on my website and give it a try in your next C++ project.

Happy coding!

Arduino Cheat Sheet Coaster, Gold Printed Circuit Board, Unique Gift for Electronic Engineers, Scientists, and Students

Arduino Cheat Sheet Coaster

I have designed this lovely coaster that reminds anyone of the perfect engineering embedded in Arduino after every sip of their coffee. It is made of high-quality printed circuit board (PCB) material, lead-free, and gold plated with nice round corners. It feels very professional and is a must if you work with electronic devices. The content of the cheat sheet is carefully chosen by me after working with Arduino for many years to include the mostly used commands and libraries.

The coaster has the drawing of Arduino Uno board pin map for quick reference, making it easy to work with Arduino in lab.

The item has the following specifications:

Dimensions: 10 cm x 10 cm [3.94" x 3.94"] Thickness: 1.6 mm [0.04"] Weight: 30g

Order Options

Arduino Cheat Sheet Coaster

You can order this coaster from my online shops (IoTUp) on these online marketplaces (for 30% discount use "THANKYOU" code at the checkout):

Share USB Devices with WSL & Docker Containers

Recently, I have faced an issue in accessing my USB JLink programmer from inside a docker container using WSL 2. I have found that this process is not well documented and requires advanced understanding of how USB devices work under WSL and inside Linux. After spending a few hours and playing with different tools and commands, I decided to document the steps I have followed here for the community.

My System Configuration

For your information, I have mentioned my system configuration here:

  • OS: Windows 11,
  • WSL: WSL 2 with Ubuntu 22.04 and Docker Desktop
  • My USB device: JLink USB Programmer from SEGGER.
  • Debugger tool: OpenOCD (still udev rules from JLink software package is requird)

I expect the process doesn't change drastically if you work on Windows 10 or you use another Linux OS for your WSL instance. However, different USB devices require different rules for udev Linux utility to make them available for non-root users.

Step 1: Install USPIPD-Win project and attach USB devices to WSL instance

Follow the steps in the official guide from Microsoft and attach your connected USB devices to your Ubuntu WSL.

Note

You need to run PowerShell as administrator and do this step every time you want to attach a USB device to your WSL. Also, after rebooting your PC or reconnecting the USB device, you have to do this step again as the attachment is temporary. I recommend keeping the PowerShell terminal open in the background if you need to disconnect and connect your device frequently. Also, if the USB devices get reset, this step has to be done again, but for debuggers like JLink this won't be an issue as they don't reset themselves, but the target.

Step 2: Fix udev rules in Ubuntu WSL (give access to non-root user)

By default in Ubuntu, USB devices are only accessible by the root user. USB serial devices will appear under /dev/ttyUSB* or /dev/ttyACM* and are accessible by non-root users if the user is in the dialout group. However, for other devices, there is this tool called udev in Ubuntu and other Linux OSs that changes the permission of the USB device based on the rules defined in /etc/udev/rules.d/* and lets the non-root users to access them.

To let udev detect your device, you need to copy the rules for JLink programmer defined 99-jlink.rules file in the JLink Software Package into the /etc/udev/rules.d/. If you use OpenOCD instead of JLink debugger utilities, you still need to copy the udev rules for JLink devices, but the reset of JLink utilities are not needed anymore.

Step 3: Enable udev service to auto start in WSL

WSL doesn't come with services enabled at boot. udev is a service program that need to run in the background to detect changes to the USB bus and the connected devices. There are two ways to auto start services in WSL on Windows 11:

  1. Enable systemd for your all WSL instances in the .wslconfig.
  2. Add the startup command to the wsl.conf file in your WSL instance.

Here I have taken the second approach as it doesn't mess with the other WSL instances. Add the following block to your to /etc/wsl.conf:

[boot]
command="service udev start"
For further information on WSL configuration and the accepted parameters check this guide from Microsoft. Windows 10 users should follow similar steps differently. Please refer to this stackoverflow response for further information.

Step 4: Share USB devices with Docker

If you have another level of virtualization for your development environment using Docker (e.g. VSCode Containerized Development Environment), you can share all of your WSL USB devices with your container by passing the following arguments to the docker run command: --privileged -v /dev/bus/usb/:/dev/bus/usb. It is also possible to share only a specific device instead of giving access to the USB bus. You can find more information in this stackoverflow response.

(Optional) Final Step

Now you see the USB devices by running the following command in your WSL and docker container:

lsusb
If your docker container doesn't have the udev utilities included, you need to add them to the docker image. If the image is based on Debian, you can install the following packages (some of them are required for OpenOCD to work):
sudo apt-get update
sudo apt-get install udev usbutils libusb-0.1-4 libusb-dev

Final Notes

Sharing USB devices with WSL in Windows 11 seems to be easier that Windows 10. I have been using it for a while and it was stable enough to be called reliable. Please contact me if you had questions/feedback or found some information here misleading for me to update.

Firmware Co-Design & Development for IP Cores in C++/SystemC using Verilator

Co-design of software and hardware for FGPA-based embedded systems has become a major challenge for tech companies, pushing them to follow development processes that require special care to lower the risks. The risk becomes a major factor for system on chip (SoC) solutions with integrated intellectual property (IP) cores that require custom firmware or driver development. A solution to this problem that has received a lot of interest in the last few years is by simulating the IPs and using them to design and validate the corresponding software stacks. Verilator is an open-source tool that is specifically developed for this purpose to simulate the IPs written in Verilog or SystemVerilog hardware description languages. In this talk, I am going to discuss the following topics for the audience:

  • A brief introduction to SystemC and simulation of logic blocks in C++
  • Common processes for co-design of firmware and FPGA IP cores
  • Introduction to Verilator and using it for creating simulation models from IP cores
  • Protecting IPs by encrypting their simulated models and sharing pre-releases
  • An example workflow for Verilog IP simulation and firmware design in C++
  • Analysis of simulation results with open source tools
  • Real-time simulation of verilated models with QEMU for system integration

The presentation slides are available on SlideShare. My video presentation is available on Embedded Online Conference 2022 website.

Communication Patterns for Distributed Control Systems and IoT Devices

There are several communication models that can be used in a distributed control system. Each model has its pros and cons, therefore the system designer has to decide which model to employ for the implementation of the control system based on what each pattern offers. In this article, several communication patterns are reviewed and compared with each other to understand their use cases. In the following, a comparative analysis has been given for a number of common communication patterns, for the purpose of the appropriate employment in distributed control systems and IoT devices.

a) Request-Response pattern, and b) Events pattern

Figure 1: a) Request-Response pattern, and b) Events pattern

1) Request-Response

This communication model is one of the most commonly known models. It consists of a client that requests a service from a server, as shown in Figure 1 (a). It is a useful model for the client-server or master-slave architectures, however, a drawback of this model is the inequality of participants, which is apparent in the network topology. This makes it difficult for the bidirectional communication scenario, in which both the parties request information from each other, especially if firewalls are present. Consequently, either events, event-subscriptions, or security is difficult to manage, and require additional services and substantial resources if firewalls are used in the network.

2) Event-Subscription

This communication model allows a client to subscribe to events of a given type from a server. The server then informs the client each time the event is triggered, without having to constantly poll the server, as in Figure 1 (b). Advanced event-subscription mechanisms can include client-­specific requirements of when events are desired and under what conditions. The benefits of using this communication model are that half of the messages are not needed over time, and the latency of updates is kept to a minimum. The problem with this model is that it is not designed for the multiparty communication scenario. This can be further solved using the publish-subscribe model.

3) Multicasting

The previous models are primarily considered for the communication purposes between two entities. However, a more efficient model is required in cases when the same information has to be sent to multiple entities at the same time. Here, a sender sends one message through an intermediary (i.e., a broker or a router) which then distributes it to multiple recipients that have all requested participation in the communication. This model saves the bandwidth because the sender does not have to send individual messages to all the parties by itself. Also, the sender does not even have to know who the recipients are.

Although one can use this model in order to save the bandwidth, it is often used as a means of overcoming the restrictions in the chosen protocol, and its support of the event-subscription model, as well. In addition, multicasting is inherently difficult to secure, and it is more efficient in terms of the bandwidth only if the recipients actually use most of the transmitted values. In the case where frequent multicasting for decreasing the latency in the network is desired but not possible, the multicasting model might result in the increase rather than decrease in the required bandwidth.

4) Queues

The first-in, first-out queues, is a model that allows one or more entities to post the messages or tasks into a queue, and then lets one or more receivers receive the messages in an ordered fashion. The queues reside on an intermediary node or network to which all participants are connected. This model is an excellent tool for the load balancing purposes, where the collected tasks from multiple sources need to be distributed among the existing workers, perhaps having different performances. Queues can hardly be used for real-time communications in control systems, since the message should be saved at first, and then be processed at the controller via an intermediary node.

5) Publish-Subscribe

This communication model is an extension of the multicasting model, with the difference that messages transmitted are stored in the intermediary node. The messages, or a reference to the messages, are distributed to the corresponding subscribers, depending on the protocol. Also, only the latest message is stored, a given number of messages are stored, or all messages are stored in the intermediary, depending on the chosen protocol, as well as the settings of the intermediary. The difference between distributing the entire message and distributing only a reference to the message is important and affects the performance of the solution in terms of the consumed bandwidth. If the subscribers consume most of the messages, forwarding the messages themselves is more efficient, as in the case of multicasting. If, however, consumption occurs only on demand, then sending shorter references is more efficient because these messages are smaller and subscribers would use only a minority of them to fetch an actual message. In order to fetch a message in the latter case, a separate request-response action needs to be performed.

The behavior of each model has been analyzed from the control point of view. In this treatise, the publish-subscribe communication model is used for the practical implementation of the distributed event-based control strategy. In the publish-subscribe model, a node can act as a publisher, subscriber, or both simultaneously. The network roles can be dynamically changed to ensure a flexibility to reconfigure the directions of the data exchange. The main advantage of this model is that the data can be exchanged intelligently between the devices (i.e., the publishers send the data to the specific subscribers without having a subscription knowledge of each node). This keeps the setup process easier for the overall maintenance of the network, and enables the self-configuration of the devices, as one of the primary characteristics of the industrial ad-hoc networks. The process of selecting messages for the reception and processing is called filtering. The topic-based and content-based filtering are the two common forms of filtering used in new communication protocols introduced in the context of IoT. In the publish-subscribe network setup, a server manages the topics and contents, which is called a broker. The broker-free setup can be achieved with the distributed topics/contents suitable for the proposed distributed control structure. The topic-based publish-subscribe communication model also enables the selective message distribution among a number of sources and sinks. Messages are associated with the topics and are selectively routed to destinations with matching topic interests. Subscribers show their interest in receiving data with a given topic and data sources publish messages on the topics.

Conclusion

In general, publish-subscribe communication is a potential solution the requirements of distributed control systems and IoT devices, however, the existence of a broker might increase communication delay in the feedback loop. The main advantages of the publish-subscribe communication model compared with the aforementioned models can be summarized as:

  • Adaptive role change in a dynamic environment from the publisher to the subscriber and vice versa.
  • Intelligent data exchange among the nodes without having a subscription knowledge of each node.
  • Automatic self-configuration of the nodes in the ad-hoc network without a central configurator which enables the plug and play operation of the control system.
  • Intrinsic discrete event transmission support which suits it as an ideal choice for the event-triggered control.

References

[1] S. A. Alavi, K. Mehran, Y. Hao, A. Rahimian, H. Mirsaeedi and V. Vahidinasab, "A Distributed Event-Triggered Control Strategy for DC Microgrids Based on Publish-Subscribe Model Over Industrial Wireless Sensor Networks," in IEEE Transactions on Smart Grid, vol. 10, no. 4, pp. 4323-4337, July 2019.

[2] S. Amir Alavi, A. Rahimian, K. Mehran and J. Mehr Ardestani, "An IoT-Based Data Collection Platform for Situational Awareness-Centric Microgrids," 2018 IEEE Canadian Conference on Electrical & Computer Engineering (CCECE), 2018, pp. 1-4.

DC-DC Buck Converter with Arduino Uno

Video of the Experiment

You can watch the video of this experiment by following this link:

DC-DC Buck Converter with Arduino Uno

Introduction

In this experiment, we want to build a cheap DC-DC buck converter using the common electronic components available online. The pulse width modulation (PWM) switching signal is generated using Arduino Uno and drives the gate of P-Channel Metal oxide silicon field effect transistor (MOSFET) through a bipolar junction transistor (BJT).

A buck converter or a step-down converter is a DC-to-DC power converter, which steps down voltage (while stepping up current) from its input (supply) to its output (load). It is a class of switched-mode power supply (SMPS), typically containing at least two semiconductors (a diode and a transistor, although modern buck converters frequently replace the diode with a second transistor used for synchronous rectification) and at least one energy storage element, a capacitor, inductor, or the two in combination. To reduce voltage ripple, filters made of capacitors (sometimes in combination with inductors) are normally added to such a converter's output (load-side filter) and input (supply-side filter).

First, the theory of DC-DC buck converter is provided. Second, the list of components used in this experiment is provided. Finally, the schematic and the circuit of the DC-DC converter is provided.

Theory of DC-DC Buck Converter Operation

A basic circuit of a buck converter is provided. In order to study how it works, we will divide it in two stages. The ON and OFF stages. In the ON state, the switch is closed as we can see in the next figure, where the diode is open because the cathode voltage is higher than the anode.

buck converter operation image

Figure 1: Basic circuit for a DC-DC buck converter

The switching transistor between the input and output of the buck converter continually switches on and off at high frequency. To maintain a continuous output, the circuit uses the energy stored in the inductor L, during the on periods of the switching transistor, to continue supplying the load during the off periods. The circuit operation depends on what is sometimes also called a Flywheel circuit. This is because the circuit acts rather like a mechanical flywheel that, given regularly spaced pulses of energy keeps spinning smoothly (outputting energy) at a steady rate.

When the switch is first closed (on-state), the current will begin to increase, and the inductor will produce an opposing voltage across its terminals in response to the changing current. This voltage drop counteracts the voltage of the source and therefore reduces the net voltage across the load. Over time, the rate of change of current decreases, and the voltage across the inductor also then decreases, increasing the voltage at the load. During this time, the inductor stores energy in the form of a magnetic field. If the switch is opened while the current is still changing, then there will always be a voltage drop across the inductor, so the net voltage at the load will always be less than the input voltage source. When the switch is ON the inductor will charge up and the voltage on the inductor will be the difference between the output and the input. But we also know that the inductor voltage is the inductance L multiplied by the inductor current derivate. As we can see in the next figure, we obtain the ON current through the inductor.

buck converter on state image

on state equations

Figure 2: ON state of the buck converter

When the switch is opened again (off-state), the voltage source will be removed from the circuit, and the current will decrease. The decreasing current will produce a voltage drop across the inductor (opposite to the drop at on-state), and now the inductor becomes a Current Source. The stored energy in the inductor's magnetic field supports the current flow through the load. This current, flowing while the input voltage source is disconnected, when concatenated with the current flowing during on-state, totals to current greater than the average input current (being zero during off-state). The "increase" in average current makes up for the reduction in voltage, and ideally preserves the power provided to the load. During the off-state, the inductor is discharging its stored energy into the rest of the circuit. If the switch is closed again before the inductor fully discharges, the voltage at the load will always be greater than zero. In this case the voltage across the inductor is the output voltage. So once again using the next figure formulas we obtain the current of the OFF part.

buck converter off state image

off state equations

Figure 3: OFF state of the buck converter

Now if we want to obtain the output depending on the input and the duty cycle of the PWM all we have to do is to make the sum of the On and Off current equal to 0. That means that the On current is equal to the Off current. So, this will give us:

input output equations

Figure 4: Input-output voltage equation

List of components for the building and testing the DC-DC buck converter

Component Quantity
IRF4905PBF 1
1N5819 1
Panasonic 100μF 16V Electrolytic Capacitor 2
150 μH ±15% Power Inductor, 2A Idc, 106mΩ Rdc 1
SS8050DTA NPN Transistor, 1.5 A, 25 V 1
1kΩ Resistor 2
10kΩ Through Hole Trimmer Potentiometer 1
Jumper wires (male to male) 10
9V battery 1
9V battery contact 1
Arduino Uno with USB cable 1
Osciloscopte 1
Breadboard 1

Building the DC-DC buck converter circuit using Arduino as the PWM source

The Arduino UNO already has a 5V linear voltage regulator that will lower the efficiency of the circuit. So the main goal is to learn how the circuit, the feedback and the PWM signal work in order to achieve the desired output.

buck_converter_schematic

Figure 5: Schematic of Arduino-based DC-DC buck converter

As you can see in the schematic above we have a potentiometer connected to the analog input A0. With this potentiometer we will choose the output value between 1 and 9 volts since the maximum input voltage in this case is 9V. With the Arduino's ADC we will read a value between 0 and 1024, next, in the code we map that value from 1 to 244 which are the values used with the analogWrite function of the Arduino. With this we will apply a PWM signal on pin D3 where 1 is the lowest duty cycle and 244 the maximum. Since the Arduino digital value is 5V we add a small BJT driver using one S8050 NPN and two resistors of 1k. The output of this driver is connected to the gate of the IRF4905 P-MOSFET.

Connect everything as in the schematic above and upload the next code to your Arduino and start moving the potentiometer. Observe the output on the oscilloscope.

This circuit is able to increase and decrease the voltage and keep that value steady for the same LOAD, in this case a 100 ohm resistor, as we can see in the picture below. But if we change the output load the discharge time of the output will change as well since for lower loads there will be a higher amount of current passing. So if the discharging time is faster or slower the duty cycle should change as well. For that we should add a feedback system to our circuit that would sense the output voltage and correct the PWM duty in order to keep the same desired value. In the next figure, you can find the real connection on the prototyping board with the connection to Arduino UNO.

buck_converter_schematic

Arduino Code for PWM Generation

#include <Arduino.h>

//Analog input pin for the potentiometer
int potentiometer_pin = A0; 

// PWM output pin
int pwm_pin = 3;          


void setup() {
  // Adjusts the pin to input mode
  pinMode(potentiometer_pin, INPUT);
  // Adjusts the pin to output mode
  pinMode(pwm_pin, OUTPUT);

  // Adjusts the PWM frequency to 980.39 Hz.
  // By default arduino PWM frequency is 490.20 Hz, 
  // but this value is not high enough to have a stable DC output voltage in low duty cycles.
  TCCR2B = TCCR2B & B11111000 | B00000011;
}

void loop() {  

  // Reads the voltage of the potentiometer to a value between 0 to 1023
  // The resolution of ADC on Arduino is 10 bits.
  int duty_cycle = analogRead(potentiometer_pin);

  // Maps the value from [0 1023] to [0 255] for the PWM function of Arduino
  int duty_cycle_mapped = map(duty_cycle, 0, 1024, 0, 254);

  // Sets the PWM signal duty cyle value, 0->0%, 254->100%
  analogWrite(pwm_pin, duty_cycle_mapped);
}

Important Notes

  • Make sure all of the components are connected correctly before connecting the battery.
  • Take enough care to keep the battery contact wires not touching each other, otherwise it will be short circuit and the battery becomes hot and loses its energy.
  • Don't forget to program the Arduino with the code provided, otherwise you won't see anything on the output.
  • Try find the resistor values by their color code. They should be 1k resistors.

Video of the Experiment

You can watch the video of this experiment by following this link: Video on Youtube