Skip to content

osharuda/home-lab-easy-kit

Repository files navigation

Home Lab Easy Kit

Home Lab Easy Kit

[TOC]

  1. Key components
  2. Hardware requirements
  3. Software requirements
  4. Usage instructions
  5. Available peripherals
  6. 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
  7. 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
  8. Building and flashing firmware
  9. Linking with generated library
  10. Example
  11. Contributing
  12. License
  13. References and literature
  14. Remarks

Description

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.

Key components

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.

Hardware requirements

  • 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.

Software requirements

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 and Raspberry Pi OS Buster is basic configuration for instructions. Other configuration may require different configuration process.
  • CMake: With version >= 3.10. Install cmake 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. Install libicu-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. Install openocd package. More information on OpenOCD project is here.
  • ST-LINK/V2 tools: This software is required to flash and debug firmware. Install stlink-tools package. More information is here
  • i2c-tools: are very useful during work with i2c bus. Install i2c-tools package.
  • doxygen: Doxygen is required to generate documentation for firmware and software parts of the project. Install doxygen 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. Install libncurses-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.

Usage instructions

List below describes sequential actions required to start:

  1. Install software dependencies.
  2. Prepare JSON configuration file(s), if needed.
  3. Run customizer with JSON configuration file passed as parameter, if you plan to use MCU.
  4. Build firmware and flash MCU, if needed.
  5. Build software and link generated library to your project.
  6. Make all electrical connections for your project.

Available peripherals

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

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

Peripherals

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.

Peripherals types table

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.

GPIO pin configuration table

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.

ADC input table

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:

ADC sampling times

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

DeskDevCustomizer

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.

RTCCustomizer

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

IRRCCustomizer

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.

LCD1602aCustomizer

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

UartProxyCustomizer

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.

GPIODevCustomizer

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

SPWMCustomizer

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.

ADCDevCustomizer

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

StepMotorDevCustomizer

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

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.

Micro stepping

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

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

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

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.

Fault

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).

CanCustomizer

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.

AD9850DevCustomizer

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

SPIDACCustomizer

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

SPIProxyCustomizer

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

STM32F10x errata

alt text

Describe here important MCU limitations

Software architecture

alt text

Place software diagram here, brief description of components

EKit class hierarchy

alt text

Place diagram with class hierarchy (??? may be to big ???) and brief description for classes

Busses

alt text

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.

Devices

alt text

More detailed description for devices, describe devices that may work via MCU only and via MCU and microcomputer buses like uart and spi

Firmwareless devices

alt text

Here is description of the devices which work is supported via MCU (proxies) and general purpose microcomputer buses.

GSMModem

alt text

SPIFlash

alt text

ADXL350

alt text

Building and flashing firmware

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 using ST-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.

Linking with generated library

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

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.

Contributing

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:

  1. 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.

  2. 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.

  3. 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.

Further development

There are a lot of ideas how to extend this project and move it forward. Among of others are:

  1. Python3 module source code generation.
  2. Adding support to other peripherals PWM (hardware), USB (as new protocol).
  3. Estimating RAM requirements for firmware.
  4. Possibility to use other MCU models.

Contact

If you want to contact me you can reach me at oleh.sharuda@gmail.com

License

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.

References and literature

  1. The Art of Electronics, by Paul Horowitz and Winfield Hill - must have if you work with electronics.
  2. STM32f103 related datasheets:
    • DS5319 - Datasheet for STM32F103C8 family of MCU. These ones are used in "Blue Pill" modules.
    • RM0008 - Datasheet for STM3210x family of MCU.
  3. SIM800 Series AT Command Manual - required if you plan to use SIM800 based GSM modem.
  4. Software part is written with C++11. This is one of the major resources for C++11.
  5. Short video demonstration of flash light radiation diagram scanning: video

Remarks

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.