[TOC]
- Key components
- Hardware requirements
- Software requirements
- Usage instructions
- Available peripherals
- JSON configuration file 6.1. Peripherals 6.1.1. Peripherals types table 6.1.2. GPIO pin configuration table 6.2. DeskDevCustomizer 6.3. RTCCustomizer 6.4. IRRCCustomizer 6.5. UartProxyCustomizer 6.6. LCD1602aCustomizer 6.7. GPIODevCustomizer 6.8. SPWMCustomizer 6.9. ADCDevCustomizer 6.10. StepMotorDevCustomizer 6.11. CanCustomizer 6.12. AD9850DevCustomizer 6.13. SPIDACCustomizer 6.14. SPIProxyCustomizer 6.15 STM32F10x errata
- Software architecture 7.1. EKit class hierarchy 7.1.1. Busses 7.1.2. Devices 7.2. Firmwareless devices 7.2.1. GSMModem 7.2.2. SPIFlash 7.2.3. ADXL350
- Building and flashing firmware
- Linking with generated library
- Example
- Contributing
- License
- References and literature
- Remarks
Purpose for Home Lab Easy Kit project is to give amateurs possibility to build experimental setups with less efforts and price to save resources for other more important objectives like experiment logic, calculations, etc. Efficiency is achieved by providing C++ libraries which implement a lot of low level work, leaving users with experiment logic and hardware wiring.
For some specific hardware-related tasks (interrupts, gpio pins polling, timers, etc.) project utilizes STM32F103C8T6 MCU with communication by i2c bus. The firmware and configuration libraries are generated from user provided JSON file. Also, using this MCU provides such features as ADC, waveform signal generation, multichannel PWM, etc. However there are devices that may be used without MCU, using microcomputer based interfaces (GSM modems, ADXL350 accelerometer, etc).
There are number of benefits provided by this solution:
- Logic and heavy calculations may be moved from micro controller to computer, which performance is generally much better.
- It is possible to use other libraries for database access, data science, networking etc.
- Communication utilizes I2C in 7-bit addressing mode. In theory you can connect up to 112 micro controllers to single I2C port.
- Firmware architecture is intended to use MCU peripherals economically to allow as much peripherals to be used per micro controller as possible.
- It is possible to use project for some type if devices without MCU at all.
For sure, user should have some theoretical and practical background related to micro controllers, electronics and what he is doing. Home Lab Easy Kit doesn't void this requirement, it just makes entrance easier and allows to save time.
Note, this project doesn't describe electrical connections and schematics, it's purpose to provide firmware and software for your design. There are a few notes related electrical circuits, treat them as advice or suggestion from inexperienced engineer and don't rely on them much. For better information regarding electrical circuits and connections read corresponding documentation and literature.
Author doesn't take any responsibility for any possible consequences. You are responsible for everything you do with this project. Be very careful with electricity, it hits fast, unexpectedly and without swing. Get corresponding knowledge before doing anything on practice.
Project consist of three parts: Customizer, Firmware and Software.
JSON configuration file
is written by user to describe peripherals on a single MCU. This file describes user requirements to customizer and allows to generate configuration library and firmware sources for this MCU. If several MCUs are required, then the same number of JSON files should be written, one file per MCU.
Customizer
generates C and C++ sources required for firmware and software parts. Also customizer is capable to detect some issues in JSON configuration and to warn user.
Firmware
part is CMSIS based firmware project written on C. It is generated from user provided JSON files. Once headers are generated by customizer it may be compiled and flashed into MCU. User is not required to change firmware sources, however it is not forbidden. If you need several MCU to be connected to your microcomputer, you will have to write the same number of JSON files (with different I2C addresses), generate several firmware binaries, and flash all of your MCUs one by one.
Software
part consists of two libraries provided to work with project:
- libhlek - is a library (doesn't require configuration) which implements all work with supported devices from microcomputer side. User program should link with this library in order to use project.
- configuration library (libconfig, optional) - is a generated library (library name is always different, based on source JSON file name) to provide information about STM32F103 MCU to be connected and used. It has description of all devices being used with the MCU. If you need to connect several MCUs to your microcomputer you will have to generate several such configuration libraries. All libraries are separated by C++ namespaces to avoid collisions.
Documentation
Documentation is split onto three parts.
- This document serves as introduction. Also it explains basic things like software and hardware requirements, JSON configuration file, etc.
- Software documentation is provided in doxygen form. It should be generated in order to get more information on classes, interfaces, etc. It is required if you plan to use this project.
- Firmware documentation is also provided in doxygen form. It is optional and incomplete. Someone, curious, may use it to understand how firmware works.
- Computer or microcomputer with Linux and possibility to connect and work with I2C bus. Software implementations of I2C bus also should work. Note, I2C will not be used in clock stretching mode. It means all Raspberry Pi versions may be used (I2C stretching bug in BCM2835 processor shouldn't be a barrier)
- STM32F103C8T6 micro controller. It may be one of "Blue pill" boards or self made PCB with this micro controller. Some part of the project may be used without MCU at all.
- STM32 ST-LINK v2 programmer or any other capable to work with STM32F103C8T6. Required only if you plan use MCU.
- Power supply capable to provide as much power as your project require. Prefer power supplies with ground line. Avoid using two or more power supplies in your project, this may cause serious issues.
Below is a description of software dependencies required to use Home Lab Easy Kit project.
The following packages are used by Home Lab Easy Kit project:
Raspberry Pi OS Buster
: This is a new version of Raspberry Pi OS to be installed on Raspberry Pi microcomputer. Other Linux distributions may also be used and configured in this way, however some packages may be missing or have different names. Note, not all of the packages may be available for previous versions (before Buster) of Raspberry Pi OS. This project is not limited by Raspberry Pi, however it is difficult to write instructions for all possible microcomputers and operational systems. So, Raspberry Pi andRaspberry Pi OS Buster
is basic configuration for instructions. Other configuration may require different configuration process.CMake
: With version >= 3.10. Installcmake
package.You may get more CMake project information here.ICU4C
: International Components for Unicode (for C/C++). It is official library from the Unicode Consortium. It is included in many Linux distributions, however in our case development files are required. Installlibicu-dev
package. You may get more information here.GNU Arm Embedded Toolchain
: It is a collection of packages required for bare-metal software development using 32-bit ARM processors. It also includes Cortex-M, used in STM32F103x. Install these packages:binutils-arm-none-eabi
,gcc-arm-none-eabi
,gdb-multiarch
. Note,tools
variable in firmware/toolchain.cmake should be modified to specify path to toolchain in order to configure project for CMake. More information about GNU Arm Embedded Toolchain project is here.STM32F10x Standard Peripherals Library
: This is a library from STMicroelectronics which is required to build firmware. It can be downloaded from ST web site directly. Unpack library and modify STDPERIF_PATH variable in firmware/toolchain.cmake. It is possible to get “registers may not be the same” compilation errors with this library. If the error appears use patch to fix it.OpenOCD
: Open On-Chip Debugger project required to debug firmware. Optionally it may be used to flash firmware, or to debug it from your favorite IDE. Installopenocd
package. More information on OpenOCD project is here.ST-LINK/V2 tools
: This software is required to flash and debug firmware. Installstlink-tools
package. More information is herei2c-tools
: are very useful during work with i2c bus. Installi2c-tools
package.doxygen
: Doxygen is required to generate documentation for firmware and software parts of the project. Installdoxygen
package. More information on Doxygen may be found here.ncurses
: This library is used for minimal terminal interface used by Home Lab Easy Kit monitor. Installlibncurses-dev
package.python3
: Required to run Customizer, which is written using Python3. Python3 should be a part of the operational system.
The following command might be used to install everything at once:
apt update && apt install vim git mc cmake libicu-dev binutils-arm-none-eabi gcc-arm-none-eabi gdb-multiarch openocd stlink-tools i2c-tools doxygen libncurses-dev
I use command above to initialize my fresh Raspberry Pi installation. Therefore there might be some unrelated packages.
List below describes sequential actions required to start:
- Install software dependencies.
- Prepare JSON configuration file(s), if needed.
- Run customizer with JSON configuration file passed as parameter, if you plan to use MCU.
- Build firmware and flash MCU, if needed.
- Build software and link generated library to your project.
- Make all electrical connections for your project.
Currently Home Lab Easy Kit support the following functionalities that represent peripherals which require STM32F103C8T6:
Name | Description | Exclusive | Remapping |
---|---|---|---|
INFODev | Firmware identification and information support | Yes | No |
ADCDev | 12-bit Analogue to Digital Converter support | No | No |
DESKDev | Simple set of four buttons and one encoder | Yes | No |
GPIODev | General purpose input/output support | Yes | No |
IRRCDev | NEC standard IR remote control support | Yes | No |
LCD1602ADev | Simple LCD1602a screen support | Yes | No |
RTCDev | Real Time Clock support | Yes | No |
SPWMDev | Multichannel software PWM support | Yes | No |
StepMotorDev | Support for A4998 and DRV8825 stepper motor drivers | No | No |
UARTDev | UART proxy ( allow to communicate with UART devices connected to micro controller ) | No | No |
CanDev | CAN bus support (beta) | No | Yes |
CanDev | CAN bus support (beta) | No | Yes |
CanDev | CAN bus support (beta) | No | Yes |
CanDev | CAN bus support (beta) | No | Yes |
Exclusive means that the only virtual device may be enabled on the particular MCU. Non-exclusive features may provide several virtual devices of similar functionality but using different peripherals and working independently.
The following is a table of devices supported that doesn't require neither MCU nor JSON file.
Name | Description | Bus type | Proxy support |
---|---|---|---|
ADXL345 | 3-axis accelerometer | SPI |
Yes |
SPIFlash | Support for some SPI based flash chips | SPI |
Yes |
GSMModem | Simple GSM modem support (SIM800, etc) | UART |
No, in development |
Proxy support
means possibility to use this device using MCU peripherals (MCU acts as an proxy).
JSON configuration file has the following structure:
{
"firmware" : {
"mcu_model" : "stm32f103",
"i2c_bus" : {
"clock_speed" : 100000,
"buffer_size" : 512,
"address" : 32,
"requires" : {"i2c" : "I2C2"}
}
},
"devices" : {
"DeskDevCustomizer" : { ... },
"RTCCustomizer" : { ... },
"IRRCCustomizer" : { ... },
"UartProxyCustomizer" : { ... },
"LCD1602aCustomizer" : { ... },
"GPIODevCustomizer": { ... },
"SPWMCustomizer": { ... },
"ADCDevCustomizer": { ... },
"StepMotorDevCustomizer": { ... },
"AD9850DevCustomizer": { ... },
"SPIDACCustomizer": { ... },
"SPIProxyCustomizer": { ... }
}
}
The first firmware
key describes basic firmware properties.
Key | Value description | Possible values | Required |
---|---|---|---|
"mcu_model" |
MCU model being used, currently the only MCU is supported | "stm32f103" | Yes |
"i2c_bus" |
Describes i2c connection with micro computer and MCU. | Object, see below | Yes |
"clock_speed" |
I2C bus clock speed. This project was tested with standard frequency only (100kHz) | 100000 | Yes |
"buffer_size" |
Size of the buffer for commands being sent from microcomputer to MCU, in bytes. | Number | Yes |
"address" |
I2C bus address. Must be valid 7-bit i2c bus address for your project. | Number | Yes |
"requires" |
This object, here and after contain description of peripherals required. | Object | Yes |
"i2c" |
Represents I2C peripherals being used for communication | "I2C1" or "I2C2" | Yes |
"devices" |
Describes required functionalities. | Object | Yes |
Each functionality is represented by corresponding key/object pair under devices
key. The only exception is INFODev - it is not described in JSON file at all and is generated automatically based on information provided. Each key under devices
must have one of these values: "DeskDevCustomizer"
, "RTCCustomizer"
, "IRRCCustomizer"
, "UartProxyCustomizer"
, "LCD1602aCustomizer"
, "GPIODevCustomizer"
, "SPWMCustomizer"
, "ADCDevCustomizer"
, "StepMotorDevCustomizer"
, "AD9850DevCustomizer"
, "SPIDACCustomizer"
, "SPIProxyCustomizer"
. Internally they are called as customizers, to reflect their ability to customize or configure MCU firmware.
Each of these keys should have one or more key/object pairs, where key is a "name" of the device and object describes device itself. Exclusive features may be represented by single device only, non-exclusive features may have more devices described. Presence of all features is not required, so leave those customizers which are required for your project.
Note, "firmware"
doesn't allow to select MCU frequency. For example, STM32F10x is configured to use 72MHz clock and it's not possible to change. Table below shows some important settings that can't be changed by JSON configuration file. The table below describes some configuration that may not be changed.
Parameter | Description | Value |
---|---|---|
MCU frequency | 72 MHz | |
Maximum output frequency | 50 MHz | |
AHB clock divider | 1 | |
APB1 clock divider | 2 | |
APB2 clock divider | 1 |
Most of the features require some peripherals from MCU. Such dependencies are described as JSON object with key equal to peripheral type and value with name of the peripheral. Most of the time name is the same as how peripheral is defined in CMSIS library. Table below describes details about peripherals types, possible values, etc.
Key (Type) | Description | Possible values (for STM32F103C8T6) |
---|---|---|
"i2c" |
I2C interface. Currently is used for communication with software only. | "I2C1" or "I2C2" |
"gpio" |
General purposes input/output pin. | "PA_0" ... "PA_15", "PB_0" ... "PB_15", "PC_13" ... "PC_15" |
"bkp" |
Backup register | "BKP_DR1" ... "BKP_DR42" |
"rtc" |
Real time clock | "RTC" |
"timer" |
Timer1 | "TIM1" ... "TIM17" |
"adc" |
Analog to digital converter | "ADC1" or "ADC2"2 |
"adc_input" |
Analog to digital converter input | "ADC_Channel_0" ... "ADC_Channel_9", "ADC_Channel_TempSensor", "ADC_Channel_Vrefint" |
"usart" |
USART interface | "USART1", "USART2", "USART3" |
"can" |
CAN bus | "CAN1", "CAN1_REMAP" |
"spi" |
SPI interface | "SPI1", "SPI1_REMAP", "SPI2" |
The following table describes pin configurations available in STM32F103x. It is general across many electronic devices, however values are taken from CMSIS library.
Value | Direction | Description |
---|---|---|
"GPIO_Mode_IN_FLOATING" |
Input | Pin is floating |
"GPIO_Mode_IPU" |
Input | Pin is pulled up to VCC |
"GPIO_Mode_IPD" |
Input | Pin is pulled down to GND |
"GPIO_Mode_Out_OD" |
Output | Open drain |
"GPIO_Mode_Out_PP" |
Output | Push pull |
Be very careful with logic levels. Some STM32F103C8T6 pins are 5v tolerant, some not. Improper electrical connection may cause a lot of harm. If doubt, refer documentation provided by manufacturer.
The table below describes ADC inputs available in STM32F103C8T6.
Value | Description | Corresponding GPIO pin | May be used with |
---|---|---|---|
"ADC_Channel_0" |
ADC input 0 | "PA_0" | "ADC1" or "ADC2" |
"ADC_Channel_1" |
ADC input 1 | "PA_1" | "ADC1" or "ADC2" |
"ADC_Channel_2" |
ADC input 2 | "PA_2" | "ADC1" or "ADC2" |
"ADC_Channel_3" |
ADC input 3 | "PA_3" | "ADC1" or "ADC2" |
"ADC_Channel_4" |
ADC input 4 | "PA_4" | "ADC1" or "ADC2" |
"ADC_Channel_5" |
ADC input 5 | "PA_5" | "ADC1" or "ADC2" |
"ADC_Channel_6" |
ADC input 6 | "PA_6" | "ADC1" or "ADC2" |
"ADC_Channel_7" |
ADC input 7 | "PA_7" | "ADC1" or "ADC2" |
"ADC_Channel_8" |
ADC input 8 | "PB_0" | "ADC1" or "ADC2" |
"ADC_Channel_9" |
ADC input 9 | "PB_1" | "ADC1" or "ADC2" |
"ADC_Channel_Vrefint" |
Internal Vref voltage | "ADC1" | |
"ADC_Channel_TempSensor" |
Internal temperature sensor | "ADC1" |
STM32F10x introduces successive approximation analog-to-digital converters, therefore it's important to control sampling time. In a few words: measurement consist of two phases: sampling and conversion. Sampling charges internal sample and hold circuit capacitors. Once sampling is done, conversion does actual conversion of sampled voltage into digital value. Table below describes sampling times constants available for STM32F10x.
Sampling requires some current from input. Improperly configured inputs connected to high impedance outputs may undercharge sampling and hold capacitors and additional measurement error will appear. Sampling time values are specified in MCU cycles and correspond to the ones available in CMSIS library:
Value | Description |
---|---|
"ADC_SampleTime_1Cycles5" |
1.5 cycles |
"ADC_SampleTime_7Cycles5" |
7.5 cycles |
"ADC_SampleTime_13Cycles5" |
13.5 cycles |
"ADC_SampleTime_28Cycles5" |
28.5 cycles |
"ADC_SampleTime_41Cycles5" |
41.5 cycles |
"ADC_SampleTime_55Cycles5" |
55.5 cycles |
"ADC_SampleTime_71Cycles5" |
71.5 cycles |
"ADC_SampleTime_239Cycles5" |
239.5 cycles |
DESKDev is a virtual device with four buttons for "up", "down", "left", "right" and one encoder. It's purpose to organize very simple menu control in conjunction with LCD1602ADev. Example JSON configuration for DeskDevCustomizer
key describing DESKDev is given below.
"DeskDevCustomizer" : {
"controls" : {
"dev_id" : 1,
"requires" : {
"up" : { "gpio" : "PA_3" },
"down" : { "gpio" : "PA_2" },
"left" : { "gpio" : "PA_5" },
"right" : { "gpio" : "PA_4" },
"encoder" : {
"A" : { "gpio" : "PA_7"},
"B" : {"gpio" : "PA_6"}
}
}
}
}
Key | Value description | Possible values | Required |
---|---|---|---|
"dev_id" |
Device id | Number, from 1 to 16 | Yes |
"requires" |
This object contain description of peripherals required. | Object | Yes |
"up" |
GPIO pin for "up" button | "gpio" |
Yes |
"down" |
GPIO pin for "down" button | "gpio" |
Yes |
"left" |
GPIO pin for "left" button | "gpio" |
Yes |
"right" |
GPIO pin for "right" button | "gpio" |
Yes |
"A" |
GPIO pin for "A" line of the encoder | "gpio" |
Yes |
"B" |
GPIO pin for "B" line of the encoder | "gpio" |
Yes |
All buttons must be normally opened, so when corresponding button is pushed (pin is pulled up), MCU will trigger an external interrupt. One button terminal must be connected to the corresponding pin, another terminal should be grounded.
RTCDev is a virtual device that provides access to the STM32F103C8T6 real time clock. This is very useful especially when micro computer doesn't have real time clock on a board. This might be an issue if no internet access is available and computer may be powered down periodically for some reason.
Example JSON configuration is given below:
"RTCCustomizer" : {
"rtc": {
"dev_id": 2,
"requires": { "bkp" : "BKP_DR1",
"rtc" : "RTC"}
}
}
Key | Value description | Possible values | Required |
---|---|---|---|
"dev_id" |
Device id | Number, [1, 15] | Yes |
"requires" |
This object contain description of peripherals required. | Object | Yes |
"bkp" |
Backup register to be used | "bkp" |
Yes |
"rtc" |
RTC to be used | "rtc" |
Yes |
IRRCDev virtual device allows to control your experimental build with IR remote controller. It must use NEC standard. This will allow you to control your experiments from short distance, from sofa for example.
Example JSON configuration for IRRCDev:
"IRRCCustomizer" : {
"irrc": {
"dev_id": 3,
"buffer_size" : 64,
"requires": {"data" : {"gpio" : "PA_1"}}
}
}
Key | Value description | Possible values | Required |
---|---|---|---|
"dev_id" |
Device id | Number, [1, 15] | Yes |
"buffer_size" |
Size of the circular buffer to store IR remote control commands, in bytes | Number, must be even | Yes |
"requires" |
This object contain description of peripherals required. | Object | Yes |
"data" |
Describes data input. Must contain "gpio" dependency. |
"gpio" |
Yes |
There are wide spectrum of special three terminal receivers (like TSOP384 series) to handle IR remote controllers optical signals. One of these, or equivalent must be connected to data pin in order to make this functionality working.
Note, there are many different types of IR remote controls. They may be different by a signal standard and by IR signal carrier frequency. In order to make your IR remote control working, the following must be true:
- IR remote control works in NEC standard. Here is a a good description of NEC standard.
- IR signal carrier frequency of your IR remote control should match with your TSOP receiver. Read IR receiver documentation carefully. This datasheet describes TSOP382x and TSOP384x families of such receivers.
LCD1602ADev virtual device allows to use simple LCD to display some short information, messages or notifications. This feature is used in conjunction with LCD1602a screens which are cheap and widely present on the market. This screen is used in 4 bit data mode to save GPIO lines. Back-light support is available as well.
"LCD1602aCustomizer" : {
"lcd": {
"dev_id" : 5,
"welcome" : ["-=RPi Extender=-"," loading ..."],
"requires" : {"enable" : {"gpio" : "PB_14"},
"reg_sel" : {"gpio" : "PB_13"},
"data4" : {"gpio" : "PB_6"},
"data5" : {"gpio" : "PB_7"},
"data6" : {"gpio" : "PB_8"},
"data7" : {"gpio" : "PB_9"},
"light" : {"gpio" : "PB_0"}
}
}
}
Key | Value description | Possible values | Required |
---|---|---|---|
"dev_id" |
Device id | Number, [1, 15] | Yes |
"welcome" |
Array with two strings. First string is default top line text, second string is default bottom line text. | Array with two strings | Yes |
"requires" |
This object contain description of peripherals required. | Object | Yes |
"enable" |
GPIO pin for enable signal | "gpio" |
Yes |
"reg_sel" |
GPIO pin for Instruction/Data Register Selection signal | "gpio" |
Yes |
"data4" |
GPIO pin for data 4 signal | "gpio" |
Yes |
"data5" |
GPIO pin for data 5 signal | "gpio" |
Yes |
"data6" |
GPIO pin for data 6 signal | "gpio" |
Yes |
"data7" |
GPIO pin for data 7 signal | "gpio" |
Yes |
"light" |
GPIO pin for back light signal | "gpio" |
Yes |
STM32F103C8T6 has three USART interfaces. UARTDev virtual device feature add possibility to use these interfaces to connected different UART devices.
"UartProxyCustomizer" : {
"uart_proxy_0" : {
"dev_id" : 4,
"hint" : "gsmmodem",
"buffer_size" : 2000,
"baud_rate" : 9600,
"requires" : { "usart" : "USART1"}
}
}
Key | Value description | Possible values | Required |
---|---|---|---|
"uart_proxy_0" |
Name of the UARTDev virtual device. | String | Yes |
"dev_id" |
Device id | Number, [1, 15] | Yes |
"hint" |
Optional hint, specifies which device is connected | "gsmmodem" | No |
"buffer_size" |
Size of the receive device buffer, in bytes | Number | Yes |
"baud_rate" |
Baud speed of communications | Number | Yes |
"requires" |
This object contain description of peripherals required. Must has dependency to "usart" interface. |
Object | Yes |
Note, this feature use two lines only: RX and TX. Other lines available for USART interfaces are not used.
GPIODev virtual device makes possible to control specific MCU pins. It's possible to use them as inputs and outputs. Other pin configurations are also available. Each pin has a name, which is a key for description objects specified in "description"
. Pins are configured during project customization, and can't be reconfigured later in run time. Example below lists two pins, one for input and one for output.
"GPIODevCustomizer": {
"gpio" : {
"dev_id": 6,
"description" : {
"in_0": { "type" : "GPIO_Mode_IPU",
"gpio" : "PA_11"
},
"out_1": { "type" : "GPIO_Mode_Out_PP",
"gpio": "PC_13",
"default": "1"
}
}
}
}
Key | Value description | Possible values | Required |
---|---|---|---|
"dev_id" |
Device id | Number, [1, 15] | Yes |
"description" |
This object contain descriptions of pins for this virtual device | Object | Yes |
"in_0" and "out_1" |
These objects contain descriptions of pins they represent | Object | Yes |
"type" |
Pin configuration | Pin configuration | Yes |
"gpio" |
Dependency to gpio pin | "gpio" |
Yes |
"default" |
Specifies default state for output pins. | 0 or 1 | Required for outputs, has no effect for inputs |
SPWMDev provides software PWM. It means that hardware PWM is not used, because of less flexible pin usage. This implementation use just one timer, and is capable to utilize all gpio outputs. However there is a price: hardware implementation is more accurate, stable, reliable and wont spent execution time in interrupt handler. Use it if you need something that doesn't require all the benefits of hardware PWM.
"SPWMCustomizer": {
"spwm" : {
"dev_id" : 7,
"prescaler" : 21,
"description" : {
"L0" : {
"type" : "GPIO_Mode_Out_PP",
"gpio" : "PB_1",
"default" : 1
}
},
"requires" : {"timer" : "TIM4"}
}
}
Key | Value description | Possible values | Required |
---|---|---|---|
"dev_id" |
Device id | Number, [1, 15] | Yes |
"description" |
This object contain descriptions of SPWMDev outputs | Object | Yes |
"prescaler" |
Timer prescaller value (see below) | Number | Yes |
"L0" |
Name of the output. Object that stores description for this specific output. | Object | Yes |
"type" |
Output pin configuration. May not be input! | Pin configuration | Yes |
"gpio" |
GPIO pin to be used as output | "gpio" |
Yes |
"default" |
Default value for the output. Default values may be either on or off | 0 or 1 | Yes |
"requires" |
This object contain timer description to be used by SPWMDev. | Object | Yes |
"Prescaller"
specifies divider for timer clock. Greater values allow to get longer PWM pulse duration, lower values decrease it. Timer counter clock frequency is described by the formula:
Where is a counter clock frequency, source timer clock, which is set in this project equal to the maximum MCU frequency . In this case prescaller is 1, therefore counter clock frequency is . Refer to MCU datasheet in order to get more information regarding timer clocking.
Note, "default"
value doesn't allow to set something between on and off. This is made intentionally to protect hardware from possible mistakes (like unintentional MCU reset).
Example:
Let's say there is BLDC motor from old HDD and ESC motor driver which is regulated with PWM. The goal is to control motor from software. Most of the ESC drivers require PWM pulse frequency equal to 50Hz. The formula above may be transformed as:
where , . In this case . Note, many ESC motor drivers require 5V PWM pulses, however STM32F103x produce 3.2V pulses, so some logical level conversion is required in this case.
ADCDev virtual device establish simple access to 12-bit ADC peripherals available in STM32F10x. STM32F103C8T6 has two ADC, both of them may be used. ADC may be used in either interrupt or DMA (Direct Memory Access) mode. Current implementation doesn't give as much performance benefits as DMA may provide. This functionality shouldn't be treated as a kind of oscilloscope for quick signal measurements. Instead of this, feature is designed to be multichannel multimeter, capable to provide data logging for slow signals. STM32F10x also allows to measure internal temperature and internal reference voltage. For fast signals it is better to consider some specialized hardware.
"ADCDevCustomizer": {
"adc_0" : {
"dev_id" : 8,
"buffer_size" : 96,
"use_dma" : 1,
"vref" : 3.2,
"sample_time" : {
"default" : "ADC_SampleTime_7Cycles5",
"override" : {"input_0" : "ADC_SampleTime_28Cycles5"}
},
"requires" : {
"ADC" : {"adc" : "ADC1"},
"TIMER" : {"timer" : "TIM2"},
"input_0" : {"adc_input" : "ADC_Channel_0"},
"input_vref" : {"adc_input" : "ADC_Channel_Vrefint"},
"input_temp" : {"adc_input" : "ADC_Channel_TempSensor"}
}
}
}
Key | Value description | Possible values | Required |
---|---|---|---|
"adc_0" |
Name of the ADCDev virtual device. | String | Yes |
"dev_id" |
Device id | Number, [1, 15] | Yes |
"buffer_size" |
Size of the internal circular buffer. It is recommended to be multiple to the number of inputs. | Number | Yes |
"use_dma" |
Instructs to use either DMA (1) or interrupt mode (0) | 0, 1 | Yes |
"vref" |
Reference voltage, used by software to return measurements in volts. Specify voltage that correspond to maximum ADC value3. | Value in volts | Yes |
"sample_time" |
This object specifies sample timings for inputs. Values correspond to the ones used by CMSIS library. | Object | Yes |
"default" |
Default sampling time for all inputs. | Sampling time | Yes |
"override" |
Contains input name/sampling times to override default sample time for some inputs. | Input name/Sampling time | Yes |
"requires" |
This object contain peripherals and inputs required by ADCDev. | Object | Yes |
"ADC" |
Object holding ADC peripheral used with this virtual device. Key value ("ADC") may be changed. | Object with "adc" |
Yes |
"TIMER" |
Object holding timer to be used with this virtual device. Timer is required for both interrupt and DMA mode. Key value ("TIMER") may be changed. | Object with "timer" |
Yes |
"input_0" |
Object holding ADC input. Key value ("input_0") specifies input name and is used in software. | Object with "adc_input" |
No |
"input_vref" |
Object holding ADC internal Vref input. Key value ("input_vref") specifies input name and is used in software. | Object with "adc_input" |
No |
"input_temp" |
Object holding ADC internal temperature sensor input. Key value ("input_temp") specifies input name and is used in software. | Object with "adc_input" |
No |
StepMotorDev provides stepper motor drivers support. Currently A4998 and DRV8825 are supported. These drivers are cheap and widely present on the market. A4998 and DRV8825 are very similar, however they have differences like fault in DRV8825 pin that allows to detect driver failure. Also this feature support logic for two endstops (hardware and software), logic for motor driver failure line, micro steps. Each stepper motor has it's own buffer for the stepper motor commands. If several motors are customized for the same virtual device, all these commands will be executed synchronously, thus stepper motor movements will be synchronized.
Supported stepper motor drivers provide a significant amount of signal lines, most of them are optional. In order to make this feature to be as flexible as possible there is just one mandatory signal that requires gpio - STEP
. All other lines are optional.
Be very careful with stepper motors. These devices consume significant current and may cause burns or fire if incorrectly connected or misused.
"StepMotorDevCustomizer": {
"motor_group_1" : {
"dev_id" : 9,
"motors" : {
"m0" : {
"buffer_size" : 512,
"steps_per_revolution" : 200,
"drive_type" : "a4998",
"default_speed" : 10000,
"error_action" : "stop",
"step" : {"gpio" : "PA_0"},
"dir" : {"default" : "CW"},
"reset" : {"gpio" : "PA_1"},
"m1" : {"default" : 0},
"m2" : {"default" : 0},
"m3" : {"default" : 0},
"enable": {"default" : "disable"},
"sleep" : {"default" : "wakeup"},
"cw_endstop" : {"position_limit" : "20000", "active_level" : "low", "action": "ignore"},
"ccw_endstop" : {"position_limit" : "-20000", "active_level" : "high", "action": "ignore"}
}
},
"requires" : { "timer" : "TIM3"}}}
Key | Value description | Possible values | Required |
---|---|---|---|
"motor_group_1" |
Virtual device name | String | Yes |
"dev_id" |
Device id | Number, [1, 15] | Yes |
"motors" |
Object that contains motors to be described | Object | Yes |
"m0" |
Object that contains "m0" motor description | Object | Yes |
"buffer_size" |
Motor circular buffer size in bytes | Number | Yes |
"steps_per_revolution" |
Motor steps per revolution value. Refer to stepper motor documentation. | Number | Yes |
"default_speed" |
Default motor speed. It is a number of microseconds between step pulses. It doesn't take into account micro stepping. | Number | Yes |
"drive_type" |
Type of the driver being used. | "drv8825", "a4998", "unknown" | Yes |
"error_action" |
Action to be made on error. "stop" will stop just this motor. "stop_all" will stop all motors in the virtual device. | "stop", "stop_all" | Yes |
"step" |
Describes gpio pin to be used for STEP signal. |
Object with "gpio" |
Yes |
"dir" |
Describes stepper motor default DIR and signal. Details here... |
Object | Yes |
"reset" |
Describes gpio pin to be used forreset signal. |
Object with "gpio" |
No |
"m1" , "m2" , "m3" |
Objects that describe micro step pins and default values. Details here... | Object | Yes |
"enable" |
Describes enable signal and default enable state. Details here... | Object | Yes |
"sleep" |
Describes sleep signal and default sleep state. Details here... | Object | Yes |
"fault" |
Object that control fault behavior. Available for DRV8825 and "unknown" drivers. Details here... | Object | No |
"cw_endstop" |
Describes clock-wise end stop. Details here... | Object | Yes |
"ccw_endstop" |
Describes counter-clock-wise end stop. Details here... | Object | Yes |
"requires" |
Describes peripherals required by the virtual device. Just one timer is required per virtual device. | Object with "timer" |
Yes |
Stepper motor direction may be clock-wise or counter-clock-wise. Optionally it may specify DIR
pin for supported stepper motor drivers.
Table below describe key/values to customize stepper motor direction:
Key | Value description | Possible values | Required |
---|---|---|---|
"default" |
Default stepper motor direction | "CW" for clock-wise, "CCW" for counter-clock-wise | Yes |
"gpio" |
Optional GPIO pin dedicated for DIR signal. |
"gpio" |
No |
Actual direction values are very related, user should define what is "clock-wise" and "counter-clock_wise" for stepper being used.
A4998 and DRV8825 use micro stepping lines in order to do micro steps ( a fraction of single step motor step ). User may either change these lines from software, or pull up or down these pins if micro steps are not required. In any case stepper motor logic implemented in firmware and software must be aware of micro steps being used. It directly impacts on stepper motor position being calculated during movement. Table below describes values to be used by "m1"
, "m2"
, "m3"
.
Key | Value description | Possible values | Required |
---|---|---|---|
"default" |
Value that describe default micro step line value. | 0 or 1 | Yes |
"gpio" |
Optional GPIO pin dedicated for corresponding stepper motor line. | "gpio" |
No |
It is possible to use GPIO pins for some of these lines, while others have no GPIO pins assigned.
ENABLE
line allows to enable/disable stepper motor driver. Table below describes values available for "enable"
key.
Key | Value description | Possible values | Required |
---|---|---|---|
"default" |
Default enable value | "enable" or "disable" | Yes |
"gpio" |
Optional GPIO pin used to control this line | "gpio" |
No |
Note, that stepper motor left enabled will consume significant current and may overheat. It is not recommended to set stepper motor "default"
value to "enable".
SLEEP
signal may put driver into sleep mode. Table below describes values for "sleep"
key:
Key | Value description | Possible values | Required |
---|---|---|---|
"default" |
Default sleep pin value | "sleep" or "wakeup" | Yes |
"gpio" |
Optional GPIO pin dedicated for the SLEEP line. |
"gpio" |
No |
End stops provide possibility to stop stepper motor when it reached some limit. Such limit may be defined by hardware by using end stop switch for example, or by software limitation. In the case of software limitation current motor position calculated by firmware is being used. Table below explains values available for both clock-wise and counter-clock-wise end stop description:
Key | Value description | Possible values | Required |
---|---|---|---|
"action" |
Action that happens when end-stop is triggered. It is possible to "ignore" it, "stop" the motor or "stop_all" motors. | "ignore", "stop", "stop_all" | Yes |
"position_limit" |
Mandatory if gpio pin is not dedicated for hardware end stop. Specify stepper motor position where stepper motor software limit will be triggered. | Number | Yes, if "gpio" is not used |
"gpio" |
Hardware end stop is used. Specifies GPIO pin to be used for this purpose. | "gpio" |
No |
"active_level" |
Active logical level that makes hardware end stop active. | "low" or "high" | Yes, if "gpio" is used |
Firmware calculates position for each stepper motor used. Position is being calculated by the following formula: , where is current position, number of full steps performed, 32 is a minimal fraction of step supported by micro stepping. If motor direction is clock-wise increases, if direction is counter-clock-wise decrease. For example, if stepper motor executes two subsequent commands to move by one counter-clock-wise and current micro stepping option will instruct to do half-step, than position will decrease by one.
If "driver_type"
is "unknown" micro stepping is not supported and motor position will change by full step every STEP
pulse.
DRV8825 is different to A4998. It has "Fault" line that may be used to detect fault conditions inside driver. Table below explains possible values to use it:
Key | Value description | Possible values | Required |
---|---|---|---|
"gpio" |
Specifies GPIO pin to be used connected to FAULT driver line. |
"gpio" |
Yes |
"active_level" |
Active logical level that indicates fault. | "low" or "high" | Yes |
"action" |
Action to be taken if FAULT becomes active. It is possible to "ignore" it, "stop" the motor or "stop_all" motors. |
"ignore", "stop", "stop_all" | Yes |
Note, "fault"
object is optional, however, if specified all values should be also specified. Also, DRV8825 active "fault"
signal is low
(grounded).
CAN is a well known industrial bus which has a lot of applications. This bus is supported by STM32F103x. Unfortunately you can't connect MCU directly to CAN bus, because transceiver is required. Luckily, there are a lot of CAN transceivers available on the market in different packages (including DIP-8) which may be used by amateurs. Refer to specific IC data sheet for scheme and etc. Note, STM32f103 may use pin remapping for CAN. Both sets of pins (PA_11
/PA_12
and PB_8
/PB_9
) are 5V tolerant, so possibly, you may use transceivers with 5V logical levels. I didn't test it: in my case I used transceiver with 5V logical level interface and simple level shifter.
Currently this functionality is under development/verification. That's why it may work unstable; Implementation may change in future and documentation may be incomplete, inexact or absent.
Use the
"CanCustomizer": {
"can_0" : {
"dev_id" : 1,
"buffered_msg_count" : 256,
"bitrate": 1000,
"requires" : {"can" : "CAN1_REMAP"}
}
}
Key | Value description | Possible values | Required |
---|---|---|---|
"can_0" |
Name of the CanDev virtual device. | String | Yes |
"dev_id" |
Device id. | Number, [1, 15] | Yes |
"buffered_msg_count" |
Size of the receive circular buffer in messages. | Number | Yes |
"bitrate" |
Bitrate for the CAN bus (in kbit/s). | 10 ,20 ,50 ,83 ,100 ,125 ,250 ,500 ,800 ,1000 |
Yes |
"requires" |
Describes peripherals required by the virtual device. Just can should be specified. |
CAN1 or CAN1_REMAP |
Yes |
Note: STM32F103x has CAN and USB sharing a dedicated SRAM memory for data transmission and reception, so it is not possible to use CAN and USB at the same time.
AD9850 chip (from Analog Devices) is a well accessed, not cheap DDS generator of sine signals. It allows control of signal frequency and phase up to 40MHz (depends on output LP filter).
"AD9850DevCustomizer": {
"dds" : {
"dev_id" : 2,
"clock_frequency": "125MHz",
"requires" : {
"D0" : {"gpio" : "PA_0"},
"D1" : {"gpio" : "PA_1"},
"D2" : {"gpio" : "PA_2"},
"D3" : {"gpio" : "PA_3"},
"D4" : {"gpio" : "PA_4"},
"D5" : {"gpio" : "PA_5"},
"D6" : {"gpio" : "PA_6"},
"D7" : {"gpio" : "PA_7"},
"W_CLK" : {"gpio" : "PA_8"},
"FQ_UD" : {"gpio" : "PA_9"},
"RESET" : {"gpio" : "PA_10"}}
}
}
Key | Value description | Possible values | Required |
---|---|---|---|
"dds" |
Name of the virtual device. | String | Yes |
"dev_id" |
Device id. | Number, [1, 15] | Yes |
"clock_frequency" |
Clock frequency used to clock AD9850. It is used to calculate frequency correctly. | Number, in MHz | Yes |
"requires" |
Describes peripherals required by the virtual device. | Object with "gpio" required pins |
Yes |
"D0" -"D7" |
Data pins | "gpio" |
Yes |
"W_CLK" |
Word load clock signal | "gpio" |
Yes |
"FQ_UD" |
Word load clock signal | "gpio" |
Yes |
"RESET" |
Reset signal | "gpio" |
Yes |
SPIDAC is a virtual device that may communicate with different spi based digital to analog convertors (DACs) and generate arbitrary waveforms.
Note, currently the only DAC tested so far is DAC7611 (configuration below is written for DAC7611), others are not guaranteed to work. It is very possible this feature will be changed in a future to provide better and more convenient interface.
"SPIDACCustomizer": {
"spidac" : {
"dev_id" : 1,
"samples_number" : 100,
"clock_phase" : "second",
"clock_polarity" : "idle_high",
"clock_speed" : "9MHz",
"frame_format" : "msb",
"frame_size" : 16,
"frames_per_sample" : 1,
"ld_mode" : "fall",
"bits_per_sample" : 12,
"channels" : {
"dac_out" : {
"index" : 0,
"min_value" : 0.0,
"max_value" : 4.0,
"default_value" : 2.0
}
},
"requires" : {"SPI" : {"spi": "SPI2"},
"TIMER" : {"timer": "TIM1"},
"LD" : {"gpio" : "PA_12"}}
}
}
Key | Value description | Possible values | Required |
---|---|---|---|
"spidac" |
Name of the virtual device. | String | Yes |
"dev_id" |
Device id. | Number, [1, 15] | Yes |
"samples_number" |
Defines size of the internal bufer to store signal. Each sample includes values for all channels. | Number | Yes |
"clock_phase" |
SPI clock phase. | first , second |
Yes |
"clock_polarity" |
SPI clock polarity. | idle_high or idle_low |
Yes |
"clock_speed" |
SPI clock speed. Note, some values may be not supported on SPI1 or SPI2 . |
70khz , 140khz , 281khz , 562khz , 1.125mhz , 2.25mhz , 4.5mhz , 9mhz , 18mhz , 36mhz |
Yes |
"frame_format" |
SPI frame format (The most or least significant bit). | Either msb or lsb |
Yes |
"frames_per_sample" |
Frames per sample (all channels). | Number | Yes |
"ld_mode" |
Describes front type of the LD pin. Do not specify if "LD" pin is not used. |
fall or rise |
No |
"bits_per_sample" |
Describes number of bits per sample (single channel value). | Number | Yes |
"channels" |
Describes DAC's channels. | Object with values describing channels | Yes |
"index" |
Channel index (as it goes in SPI transaction). | String | Yes |
"min_value" |
Minimum signal value. | FP value | Yes |
"max_value" |
Maximum signal value. | FP value | Yes |
"default_value" |
Default signal value. | FP value | Yes |
"requires" |
Describes peripherals required by the virtual device. | Object with required peripherals | Yes |
"SPI" |
SPI to be used. | "SPI1" , "SPI2" |
Yes |
"TIMER" |
Word load clock signal | "timer" |
Yes |
"LD" |
Optional, this is a pin to pass LD signal for some DACs. Do not specify it if LD pin is not used. | "gpio" |
No |
SPI proxy may act as proxy for SPI devices. Surely, you may use SPI interface from microcomputer, but, if it's not available or busy by something else it is possible to use the one from MCU.
"SPIProxyCustomizer": {
"spiproxy" : {
"dev_id" : 1,
"use_dma" : 1,
"bidirectional" : 1,
"buffer_size" : 256,
"clock_phase" : "first",
"clock_polarity" : "idle_low",
"clock_speed" : "281KHz",
"frame_format" : "msb",
"frame_size" : 8,
"requires" : { "SPI" : {"spi": "SPI1"}}
}
}
Key | Value description | Possible values | Required |
---|---|---|---|
"spiproxy" |
Name of the virtual device. | String | Yes |
"dev_id" |
Device id. | Number, [1, 15] | Yes |
"use_dma" |
Instructs to use SPI in dma mode. | 0 , 1 |
Yes |
"bidirectional" |
Bidirectional communication. | 0 , 1 |
Yes |
"buffer_size" |
Size of the buffer. | Number | Yes |
"clock_phase" |
SPI clock phase. | first , second |
Yes |
"clock_polarity" |
SPI clock polarity. | idle_high or idle_low |
Yes |
"clock_speed" |
SPI clock speed. Note, some values may be not supported on SPI1 or SPI2 . |
70khz , 140khz , 281khz , 562khz , 1.125mhz , 2.25mhz , 4.5mhz , 9mhz , 18mhz , 36mhz |
Yes |
"frame_format" |
SPI frame format (The most or least significant bit). | Either msb or lsb |
Yes |
"frame_size" |
Size of the frame in bits. | 8 , 16 |
Yes |
"requires" |
Describes peripherals required by the virtual device. | Object with required peripherals | Yes |
"SPI" |
SPI to be used. | "SPI1" , "SPI2" |
Yes |
Describe here important MCU limitations
Place software diagram here, brief description of components
Place diagram with class hierarchy (??? may be to big ???) and brief description for classes
More detailed description for busses, the difference between them
SPI BUS: !!!! IMPORT NOTE ON SPI: TO ENABLE CS SIGNAL /boot/config.txt should be modified as: dtparam=spi=on dtoverlay=spi0-hw-cs
raspi-config doesn't set spi0-hw-cs, so CS line won't work if "dtoverlay=spi0-hw-cs" is not spicified.
More detailed description for devices, describe devices that may work via MCU only and via MCU and microcomputer buses like uart and spi
Here is description of the devices which work is supported via MCU (proxies) and general purpose microcomputer buses.
If MCU is needed and JSON configuration file is ready, it is time to customize project. To do this execute the following command from project root directory:
./customize.sh <JSON configuration file>
Inspect the output for warnings and errors. If successful you may build firmware and software manually. If JSON configuration file describes configuration that has conflicts, mistakes or can't be implemented than corresponding error will be shown. Errors and warnings may have different nature, for example if JSON configuration file uses the same GPIO pin for different purposes, the error will be thrown. Possibly, you will have to refer to the MCU documentation in order to understand and fix them correctly.
To do everything at once, automatically you may use build.sh
script to compile and install all required libraries by running single script:
./build.sh <JSON 1> ... <JSON n> <RELEASE>
where <JSON x>
is a JSON file to be configured, and optional RELEASE
instructs to build everything with release configuration.
Running this script will create n direcrories (one per JSON file) with corresponding firmware, libconfig, monitor test utility (for the particular JSON file) and example project. All these projects will be built, configurational libraries will be installed. Additionally to this libhlek library will be built and installed. Library installation assume you will have to pass super user credentials. If libhlek
library building is not required, you may specify NO_LIBHLEK=1
prefix to omit it:
NO_LIBHLEK=1 ./build.sh <JSON 1> ... <JSON n> <RELEASE>
It is possible to use either micro computer or PC as building machine. Technically you don’t need separate computer and may work on microcomputer, however good PC with Linux seems to be better option. There are some scripts that will help you to build and flash firmware. Note, this scripts have some hard coded values which may be different to your build.
<project>/firmware/flash.sh
- This script will flash firmware to your MCU usingST-LINK/V2 tools
.gendox.sh
- Will generate documentation using Doxygen.
It is possible to flash and debug firmware using OpenOCD
and GDB
. There are many internet resources describing this possibility, sometimes this option is very useful, especially during heavy debugging.
Options to build and flash are not limited to these ones above. There are many other ways to do this job, I just mentioned most common way from my point of view.
Note: install directories are configured in global.json
file. If you need to change install location, modify this file accordingly.
There are many ways to link generated library with main program. It worth to look how Home Lab Easy Kit monitor utility or example test program are linked with library. You may see it in <project>/monitor/CMakeLists.txt
or <project>/example/CMakeLists.txt
script.
An example project is generated in software/example
. This is project has no functionality; it's purpose is to provide understanding how to link with installed library.
Example experiment5 was built to demonstrate idea for this project. The goal is to get radiation pattern of some source of light. All sources and description is maintained in misc/radiation_pattern
.
Everyone is welcome to participate this project. Discuss changes you want to make with author first before doing pull request. I do not promise the answer will be quick, however I'll try to respond to everyone.
Contribution may be made in several forms:
-
Testing. There were some testing, but it's not enough. I am certain there are bugs, I hope not many of them. Using the project and submitting issues will be very helpful.
-
Code review. This is my first open source project with STM32, and I understand lack of experience I have. So, it would be great if some one more experienced review this project, approaches I used, etc. Probably, this will result some features to be rewritten from the ground.
-
Documentation is very important. Currently documentation required to start work with the project is ready, however there are still many dark corners to be documented. Also, English is not my native language, so, fixing grammar, syntax mistakes is always good.
There are a lot of ideas how to extend this project and move it forward. Among of others are:
- Python3 module source code generation.
- Adding support to other peripherals PWM (hardware), USB (as new protocol).
- Estimating RAM requirements for firmware.
- Possibility to use other MCU models.
If you want to contact me you can reach me at oleh.sharuda@gmail.com
Copyright 2021 Oleh Sharuda <oleh.sharuda@gmail.com>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
- The Art of Electronics, by Paul Horowitz and Winfield Hill - must have if you work with electronics.
- STM32f103 related datasheets:
- SIM800 Series AT Command Manual - required if you plan to use SIM800 based GSM modem.
- Software part is written with C++11. This is one of the major resources for C++11.
- Short video demonstration of flash light radiation diagram scanning: video
1. STM32 describes several timer types with different features and possibilities. Some features of Home Lab Easy Kit may require some specific timers. In this case it will be stated separately.
2. Some other MCU from STM32F10x family may have ADC3 onboard. To use it light modification of customizer/stm32f103.py is required.
3. "Blue Pill" goes in LQFP48 package. These MCU have connected to internally ( is connected to the ). In this case you have to specify voltage. Also, you may use "ADC_Channel_Vrefint"
channel to measure reference voltage and to calculate . Read more details in corresponding documentation provided by manufacturer.