first
This commit is contained in:
567
extras/ci/platformio.ini
Normal file
567
extras/ci/platformio.ini
Normal file
@@ -0,0 +1,567 @@
|
||||
; PlatformIO Project Configuration File
|
||||
;
|
||||
; Build options: build flags, source filter
|
||||
; Upload options: custom upload port, speed and extra flags
|
||||
; Library options: dependencies, extra library storages
|
||||
; Advanced options: extra scripting
|
||||
;
|
||||
; Please visit documentation for the other options and examples
|
||||
; https://docs.platformio.org/page/projectconf.html
|
||||
;
|
||||
; use build_flags = -E -DM
|
||||
; to get all preprocessor symbols in .pio/build/xx/src/StepperDemo.cpp.o
|
||||
;
|
||||
[platformio]
|
||||
|
||||
[env:esp32_tasmota_3_0_0]
|
||||
platform = https://github.com/tasmota/platform-espressif32/releases/download/2024.05.12/platform-espressif32.zip
|
||||
board = esp32dev
|
||||
framework = arduino
|
||||
build_flags = -Wall -DCORE_DEBUG_LEVEL=6 -DLOG_LOCAL_LEVEL=6
|
||||
board_build.f_cpu = 240000000L
|
||||
lib_extra_dirs = ../../..
|
||||
|
||||
[env:esp32_tasmota_2_0_15]
|
||||
platform = https://github.com/tasmota/platform-espressif32/releases/download/2024.04.00/platform-espressif32.zip
|
||||
board = esp32dev
|
||||
framework = arduino
|
||||
build_flags = -Wall -DCORE_DEBUG_LEVEL=5
|
||||
board_build.f_cpu = 240000000L
|
||||
lib_extra_dirs = ../../..
|
||||
|
||||
[env:esp32]
|
||||
platform = espressif32
|
||||
board = esp32dev
|
||||
framework = arduino
|
||||
build_flags = -Wall
|
||||
board_build.f_cpu = 240000000L
|
||||
lib_extra_dirs = ../../..
|
||||
|
||||
[env:esp32_V6_9_0]
|
||||
platform = espressif32 @ 6.9.0
|
||||
board = esp32dev
|
||||
framework = arduino
|
||||
build_flags = -Wall
|
||||
board_build.f_cpu = 240000000L
|
||||
lib_extra_dirs = ../../..
|
||||
|
||||
[env:esp32_V6_8_1]
|
||||
platform = espressif32 @ 6.8.1
|
||||
board = esp32dev
|
||||
framework = arduino
|
||||
build_flags = -Wall
|
||||
board_build.f_cpu = 240000000L
|
||||
lib_extra_dirs = ../../..
|
||||
|
||||
[env:esp32_V6_8_0]
|
||||
platform = espressif32 @ 6.8.0
|
||||
board = esp32dev
|
||||
framework = arduino
|
||||
build_flags = -Wall
|
||||
board_build.f_cpu = 240000000L
|
||||
lib_extra_dirs = ../../..
|
||||
|
||||
[env:esp32_V6_7_0]
|
||||
platform = espressif32 @ 6.7.0
|
||||
board = esp32dev
|
||||
framework = arduino
|
||||
build_flags = -Wall
|
||||
board_build.f_cpu = 240000000L
|
||||
lib_extra_dirs = ../../..
|
||||
|
||||
[env:esp32_V6_6_0]
|
||||
platform = espressif32 @ 6.6.0
|
||||
board = esp32dev
|
||||
framework = arduino
|
||||
build_flags = -Wall
|
||||
board_build.f_cpu = 240000000L
|
||||
lib_extra_dirs = ../../..
|
||||
|
||||
[env:esp32_V6_5_0]
|
||||
platform = espressif32 @ 6.5.0
|
||||
board = esp32dev
|
||||
framework = arduino
|
||||
build_flags = -Wall
|
||||
board_build.f_cpu = 240000000L
|
||||
lib_extra_dirs = ../../..
|
||||
|
||||
[env:esp32_V6_4_0]
|
||||
platform = espressif32 @ 6.4.0
|
||||
board = esp32dev
|
||||
framework = arduino
|
||||
build_flags = -Werror -Wall
|
||||
board_build.f_cpu = 240000000L
|
||||
lib_extra_dirs = ../../..
|
||||
|
||||
[env:esp32_V6_3_2]
|
||||
platform = espressif32 @ 6.3.2
|
||||
board = esp32dev
|
||||
framework = arduino
|
||||
build_flags = -Werror -Wall
|
||||
board_build.f_cpu = 240000000L
|
||||
lib_extra_dirs = ../../..
|
||||
|
||||
[env:esp32_V6_2_0]
|
||||
platform = espressif32 @ 6.2.0
|
||||
board = esp32dev
|
||||
framework = arduino
|
||||
build_flags = -Werror -Wall
|
||||
board_build.f_cpu = 240000000L
|
||||
lib_extra_dirs = ../../..
|
||||
|
||||
[env:esp32_V6_1_0]
|
||||
platform = espressif32 @ 6.1.0
|
||||
board = esp32dev
|
||||
framework = arduino
|
||||
build_flags = -Werror -Wall
|
||||
board_build.f_cpu = 240000000L
|
||||
lib_extra_dirs = ../../..
|
||||
|
||||
[env:esp32_V6_0_1]
|
||||
platform = espressif32 @ 6.0.1
|
||||
board = esp32dev
|
||||
framework = arduino
|
||||
build_flags = -Werror -Wall
|
||||
board_build.f_cpu = 240000000L
|
||||
lib_extra_dirs = ../../..
|
||||
|
||||
[env:esp32_V5_3_0]
|
||||
platform = espressif32 @ 5.3.0
|
||||
board = esp32dev
|
||||
framework = arduino
|
||||
build_flags = -Werror -Wall
|
||||
board_build.f_cpu = 240000000L
|
||||
lib_extra_dirs = ../../..
|
||||
|
||||
[env:esp32_V5_2_0]
|
||||
platform = espressif32 @ 5.2.0
|
||||
board = esp32dev
|
||||
framework = arduino
|
||||
build_flags = -Werror -Wall
|
||||
board_build.f_cpu = 240000000L
|
||||
lib_extra_dirs = ../../..
|
||||
|
||||
[env:esp32_V5_1_1]
|
||||
platform = espressif32 @ 5.1.1
|
||||
board = esp32dev
|
||||
framework = arduino
|
||||
build_flags = -Werror -Wall
|
||||
board_build.f_cpu = 240000000L
|
||||
lib_extra_dirs = ../../..
|
||||
|
||||
[env:esp32_V5_0_0]
|
||||
platform = espressif32 @ 5.0.0
|
||||
board = esp32dev
|
||||
framework = arduino
|
||||
build_flags = -Werror -Wall -Wno-unused-variable
|
||||
board_build.f_cpu = 240000000L
|
||||
lib_extra_dirs = ../../..
|
||||
|
||||
[env:esp32_V4_4_0]
|
||||
platform = espressif32 @ 4.4.0
|
||||
board = esp32dev
|
||||
framework = arduino
|
||||
build_flags = -Werror -Wall -Wno-unused-variable
|
||||
board_build.f_cpu = 240000000L
|
||||
lib_extra_dirs = ../../..
|
||||
|
||||
[env:esp32_V4_3_0]
|
||||
platform = espressif32 @ 4.3.0
|
||||
board = esp32dev
|
||||
framework = arduino
|
||||
build_flags = -Werror -Wall -Wno-unused-variable
|
||||
board_build.f_cpu = 240000000L
|
||||
lib_extra_dirs = ../../..
|
||||
|
||||
[env:esp32_V4_2_0]
|
||||
platform = espressif32 @ 4.2.0
|
||||
board = esp32dev
|
||||
framework = arduino
|
||||
build_flags = -Werror -Wall -Wno-unused-variable
|
||||
board_build.f_cpu = 240000000L
|
||||
lib_extra_dirs = ../../..
|
||||
|
||||
[env:esp32_V4_1_0]
|
||||
platform = espressif32 @ 4.1.0
|
||||
board = esp32dev
|
||||
framework = arduino
|
||||
build_flags = -Werror -Wall -Wno-unused-variable -Wno-deprecated-declarations
|
||||
board_build.f_cpu = 240000000L
|
||||
lib_extra_dirs = ../../..
|
||||
|
||||
[env:esp32s2_V6_9_0]
|
||||
platform = espressif32 @ 6.9.0
|
||||
board = esp32-s2-saola-1
|
||||
framework = arduino
|
||||
build_flags = -Wall
|
||||
board_build.f_cpu = 240000000L
|
||||
lib_extra_dirs = ../../..
|
||||
|
||||
[env:esp32s2_V6_8_1]
|
||||
platform = espressif32 @ 6.8.1
|
||||
board = esp32-s2-saola-1
|
||||
framework = arduino
|
||||
build_flags = -Wall
|
||||
board_build.f_cpu = 240000000L
|
||||
lib_extra_dirs = ../../..
|
||||
|
||||
[env:esp32s2_V6_8_0]
|
||||
platform = espressif32 @ 6.8.0
|
||||
board = esp32-s2-saola-1
|
||||
framework = arduino
|
||||
build_flags = -Wall
|
||||
board_build.f_cpu = 240000000L
|
||||
lib_extra_dirs = ../../..
|
||||
|
||||
[env:esp32s2_V6_7_0]
|
||||
platform = espressif32 @ 6.7.0
|
||||
board = esp32-s2-saola-1
|
||||
framework = arduino
|
||||
build_flags = -Wall
|
||||
board_build.f_cpu = 240000000L
|
||||
lib_extra_dirs = ../../..
|
||||
|
||||
[env:esp32s2_V6_6_0]
|
||||
platform = espressif32 @ 6.6.0
|
||||
board = esp32-s2-saola-1
|
||||
framework = arduino
|
||||
build_flags = -Wall
|
||||
board_build.f_cpu = 240000000L
|
||||
lib_extra_dirs = ../../..
|
||||
|
||||
[env:esp32s2_V6_5_0]
|
||||
platform = espressif32 @ 6.5.0
|
||||
board = esp32-s2-saola-1
|
||||
framework = arduino
|
||||
build_flags = -Wall
|
||||
board_build.f_cpu = 240000000L
|
||||
lib_extra_dirs = ../../..
|
||||
|
||||
[env:esp32s3_V6_9_0]
|
||||
platform = espressif32 @ 6.9.0
|
||||
board = esp32-s3-devkitc-1
|
||||
framework = arduino
|
||||
build_flags = -Wall
|
||||
board_build.f_cpu = 240000000L
|
||||
lib_extra_dirs = ../../..
|
||||
|
||||
[env:esp32s3_V6_8_1]
|
||||
platform = espressif32 @ 6.8.1
|
||||
board = esp32-s3-devkitc-1
|
||||
framework = arduino
|
||||
build_flags = -Wall
|
||||
board_build.f_cpu = 240000000L
|
||||
lib_extra_dirs = ../../..
|
||||
|
||||
[env:esp32s3_V6_8_0]
|
||||
platform = espressif32 @ 6.8.0
|
||||
board = esp32-s3-devkitc-1
|
||||
framework = arduino
|
||||
build_flags = -Wall
|
||||
board_build.f_cpu = 240000000L
|
||||
lib_extra_dirs = ../../..
|
||||
|
||||
[env:esp32s3_V6_7_0]
|
||||
platform = espressif32 @ 6.7.0
|
||||
board = esp32-s3-devkitc-1
|
||||
framework = arduino
|
||||
build_flags = -Wall
|
||||
board_build.f_cpu = 240000000L
|
||||
lib_extra_dirs = ../../..
|
||||
|
||||
[env:esp32s3_V6_6_0]
|
||||
platform = espressif32 @ 6.6.0
|
||||
board = esp32-s3-devkitc-1
|
||||
framework = arduino
|
||||
build_flags = -Wall
|
||||
board_build.f_cpu = 240000000L
|
||||
lib_extra_dirs = ../../..
|
||||
|
||||
[env:esp32s3_V6_5_0]
|
||||
platform = espressif32 @ 6.5.0
|
||||
board = esp32-s3-devkitc-1
|
||||
framework = arduino
|
||||
build_flags = -Wall
|
||||
board_build.f_cpu = 240000000L
|
||||
lib_extra_dirs = ../../..
|
||||
|
||||
[env:esp32c3_V6_9_0]
|
||||
platform = espressif32 @ 6.9.0
|
||||
board = esp32-c3-devkitm-1
|
||||
framework = arduino
|
||||
build_flags = -Wall
|
||||
board_build.f_cpu = 240000000L
|
||||
lib_extra_dirs = ../../..
|
||||
|
||||
[env:esp32c3_V6_8_1]
|
||||
platform = espressif32 @ 6.8.1
|
||||
board = esp32-c3-devkitm-1
|
||||
framework = arduino
|
||||
build_flags = -Wall
|
||||
board_build.f_cpu = 240000000L
|
||||
lib_extra_dirs = ../../..
|
||||
|
||||
[env:esp32c3_V6_8_0]
|
||||
platform = espressif32 @ 6.8.0
|
||||
board = esp32-c3-devkitm-1
|
||||
framework = arduino
|
||||
build_flags = -Wall
|
||||
board_build.f_cpu = 240000000L
|
||||
lib_extra_dirs = ../../..
|
||||
|
||||
[env:esp32c3_V6_7_0]
|
||||
platform = espressif32 @ 6.7.0
|
||||
board = esp32-c3-devkitm-1
|
||||
framework = arduino
|
||||
build_flags = -Wall
|
||||
board_build.f_cpu = 240000000L
|
||||
lib_extra_dirs = ../../..
|
||||
|
||||
[env:esp32c3_V6_6_0]
|
||||
platform = espressif32 @ 6.6.0
|
||||
board = esp32-c3-devkitm-1
|
||||
framework = arduino
|
||||
build_flags = -Wall
|
||||
board_build.f_cpu = 240000000L
|
||||
lib_extra_dirs = ../../..
|
||||
|
||||
[env:esp32c3_V6_5_0]
|
||||
platform = espressif32 @ 6.5.0
|
||||
board = esp32-c3-devkitm-1
|
||||
framework = arduino
|
||||
build_flags = -Wall
|
||||
board_build.f_cpu = 240000000L
|
||||
lib_extra_dirs = ../../..
|
||||
|
||||
[env:esp32_idf_V6_9_0]
|
||||
platform = espressif32 @ 6.9.0
|
||||
board = esp32dev
|
||||
framework = espidf
|
||||
build_flags = -Werror -Wall -Wno-deprecated-declarations -Wno-error=incompatible-pointer-types -Wno-unused-function -Wno-error=attributes -DCONFIG_RMT_ENABLE_DEBUG_LOG=5
|
||||
board_build.f_cpu = 240000000L
|
||||
lib_extra_dirs = ../..
|
||||
|
||||
[env:esp32_idf_V6_8_1]
|
||||
platform = espressif32 @ 6.8.1
|
||||
board = esp32dev
|
||||
framework = espidf
|
||||
build_flags = -Werror -Wall -Wno-deprecated-declarations -Wno-error=incompatible-pointer-types -Wno-unused-function -Wno-error=attributes -DCONFIG_RMT_ENABLE_DEBUG_LOG=5
|
||||
board_build.f_cpu = 240000000L
|
||||
lib_extra_dirs = ../..
|
||||
|
||||
[env:esp32_idf_V6_7_0]
|
||||
platform = espressif32 @ 6.7.0
|
||||
board = esp32dev
|
||||
framework = espidf
|
||||
build_flags = -Werror -Wall -Wno-deprecated-declarations -Wno-error=incompatible-pointer-types -Wno-unused-function -Wno-error=attributes -DCONFIG_RMT_ENABLE_DEBUG_LOG=5
|
||||
board_build.f_cpu = 240000000L
|
||||
lib_extra_dirs = ../..
|
||||
|
||||
[env:esp32_idf_V5_3_0]
|
||||
platform = espressif32 @ 5.3.0
|
||||
board = esp32dev
|
||||
framework = espidf
|
||||
build_flags = -Werror -Wall -Wno-deprecated-declarations -Wno-error=incompatible-pointer-types -Wno-unused-function -Wno-error=attributes
|
||||
board_build.f_cpu = 240000000L
|
||||
lib_extra_dirs = ../..
|
||||
|
||||
[env:esp32_idf_V5_2_0]
|
||||
platform = espressif32 @ 5.2.0
|
||||
board = esp32dev
|
||||
framework = espidf
|
||||
build_flags = -Werror -Wall -Wno-deprecated-declarations -Wno-error=incompatible-pointer-types -Wno-unused-function -Wno-error=attributes
|
||||
board_build.f_cpu = 240000000L
|
||||
lib_extra_dirs = ../..
|
||||
|
||||
[env:esp32_idf_V5_1_0]
|
||||
platform = espressif32 @ 5.1.0
|
||||
board = esp32dev
|
||||
framework = espidf
|
||||
build_flags = -Werror -Wall -Wno-deprecated-declarations -Wno-error=incompatible-pointer-types -Wno-unused-function -Wno-error=attributes
|
||||
board_build.f_cpu = 240000000L
|
||||
lib_extra_dirs = ../..
|
||||
|
||||
[env:esp32_idf_V5_0_0]
|
||||
platform = espressif32 @ 5.0.0
|
||||
board = esp32dev
|
||||
framework = espidf
|
||||
build_flags = -Werror -Wall -Wno-deprecated-declarations -Wno-error=incompatible-pointer-types -Wno-unused-function -Wno-error=attributes
|
||||
board_build.f_cpu = 240000000L
|
||||
lib_extra_dirs = ../..
|
||||
|
||||
#[env:esp32_idf_V4_4_0]
|
||||
#platform = espressif32 @ 4.4.0
|
||||
#board = esp32dev
|
||||
#framework = espidf
|
||||
#build_flags = -Werror -Wall -Wno-deprecated-declarations -Wno-error=incompatible-pointer-types -Wno-unused-function -Wno-error=attributes
|
||||
#board_build.f_cpu = 240000000L
|
||||
#lib_extra_dirs = ../../
|
||||
|
||||
[env:esp32c3_idf_V6_9_0]
|
||||
platform = espressif32 @ 6.9.0
|
||||
board = esp32-c3-devkitm-1
|
||||
framework = espidf
|
||||
build_flags = -Werror -Wall -Wno-deprecated-declarations -Wno-error=incompatible-pointer-types -Wno-unused-function -Wno-error=attributes
|
||||
board_build.f_cpu = 240000000L
|
||||
lib_extra_dirs = ../..
|
||||
|
||||
[env:esp32c3_idf_V6_8_1]
|
||||
platform = espressif32 @ 6.8.1
|
||||
board = esp32-c3-devkitm-1
|
||||
framework = espidf
|
||||
build_flags = -Werror -Wall -Wno-deprecated-declarations -Wno-error=incompatible-pointer-types -Wno-unused-function -Wno-error=attributes
|
||||
board_build.f_cpu = 240000000L
|
||||
lib_extra_dirs = ../..
|
||||
|
||||
[env:esp32c3_idf_V5_3_0]
|
||||
platform = espressif32 @ 5.3.0
|
||||
board = esp32-c3-devkitm-1
|
||||
framework = espidf
|
||||
build_flags = -Werror -Wall -Wno-deprecated-declarations -Wno-error=incompatible-pointer-types -Wno-unused-function -Wno-error=attributes
|
||||
board_build.f_cpu = 240000000L
|
||||
lib_extra_dirs = ../..
|
||||
|
||||
[env:esp32s2_idf_V6_9_0]
|
||||
platform = espressif32 @ 6.9.0
|
||||
board = esp32-s2-saola-1
|
||||
framework = espidf
|
||||
build_flags = -Werror -Wall -Wno-deprecated-declarations -Wno-error=incompatible-pointer-types -Wno-unused-function -Wno-error=attributes
|
||||
board_build.f_cpu = 240000000L
|
||||
lib_extra_dirs = ../..
|
||||
|
||||
[env:esp32s2_idf_V6_8_1]
|
||||
platform = espressif32 @ 6.8.1
|
||||
board = esp32-s2-saola-1
|
||||
framework = espidf
|
||||
build_flags = -Werror -Wall -Wno-deprecated-declarations -Wno-error=incompatible-pointer-types -Wno-unused-function -Wno-error=attributes
|
||||
board_build.f_cpu = 240000000L
|
||||
lib_extra_dirs = ../..
|
||||
|
||||
[env:esp32s2_idf_V5_3_0]
|
||||
platform = espressif32 @ 5.3.0
|
||||
board = esp32-s2-saola-1
|
||||
framework = espidf
|
||||
build_flags = -Werror -Wall -Wno-deprecated-declarations -Wno-error=incompatible-pointer-types -Wno-unused-function -Wno-error=attributes
|
||||
board_build.f_cpu = 240000000L
|
||||
lib_extra_dirs = ../..
|
||||
|
||||
[env:esp32s3_idf_V6_9_0]
|
||||
platform = espressif32 @ 6.9.0
|
||||
board = esp32-s3-devkitc-1
|
||||
framework = espidf
|
||||
build_flags = -Werror -Wall -Wno-deprecated-declarations -Wno-error=incompatible-pointer-types -Wno-unused-function -Wno-error=attributes
|
||||
board_build.f_cpu = 240000000L
|
||||
lib_extra_dirs = ../..
|
||||
|
||||
[env:esp32s3_idf_V6_8_1]
|
||||
platform = espressif32 @ 6.8.1
|
||||
board = esp32-s3-devkitc-1
|
||||
framework = espidf
|
||||
build_flags = -Werror -Wall -Wno-deprecated-declarations -Wno-error=incompatible-pointer-types -Wno-unused-function -Wno-error=attributes
|
||||
board_build.f_cpu = 240000000L
|
||||
lib_extra_dirs = ../..
|
||||
|
||||
[env:esp32s3_idf_V5_3_0]
|
||||
platform = espressif32 @ 5.3.0
|
||||
board = esp32-s3-devkitc-1
|
||||
framework = espidf
|
||||
build_flags = -Werror -Wall -Wno-deprecated-declarations -Wno-error=incompatible-pointer-types -Wno-unused-function -Wno-error=attributes
|
||||
board_build.f_cpu = 240000000L
|
||||
lib_extra_dirs = ../..
|
||||
|
||||
[env:esp32c6_idf_V6_9_0]
|
||||
platform = espressif32 @ 6.9.0
|
||||
board = esp32-c6-devkitm-1
|
||||
framework = espidf
|
||||
build_flags = -Werror -Wall -Wno-deprecated-declarations -Wno-error=incompatible-pointer-types -Wno-unused-function -Wno-error=attributes
|
||||
board_build.f_cpu = 240000000L
|
||||
lib_extra_dirs = ../..
|
||||
|
||||
[env:esp32c6_idf_V6_8_1]
|
||||
platform = espressif32 @ 6.8.1
|
||||
board = esp32-c6-devkitm-1
|
||||
framework = espidf
|
||||
build_flags = -Werror -Wall -Wno-deprecated-declarations -Wno-error=incompatible-pointer-types -Wno-unused-function -Wno-error=attributes
|
||||
board_build.f_cpu = 240000000L
|
||||
lib_extra_dirs = ../..
|
||||
|
||||
[env:esp32h2_idf_V6_9_0]
|
||||
platform = espressif32 @ 6.9.0
|
||||
board = esp32-h2-devkitm-1
|
||||
framework = espidf
|
||||
build_flags = -Werror -Wall -Wno-deprecated-declarations -Wno-error=incompatible-pointer-types -Wno-unused-function -Wno-error=attributes
|
||||
board_build.f_cpu = 240000000L
|
||||
lib_extra_dirs = ../..
|
||||
|
||||
[env:esp32h2_idf_V6_8_1]
|
||||
platform = espressif32 @ 6.8.1
|
||||
board = esp32-h2-devkitm-1
|
||||
framework = espidf
|
||||
build_flags = -Werror -Wall -Wno-deprecated-declarations -Wno-error=incompatible-pointer-types -Wno-unused-function -Wno-error=attributes
|
||||
board_build.f_cpu = 240000000L
|
||||
lib_extra_dirs = ../..
|
||||
|
||||
#[env:esp32s2]
|
||||
#board = esp32-s2-saola-1
|
||||
#framework = arduino
|
||||
#platform = https://github.com/tasmota/platform-espressif32/releases/download/2023.04.02/platform-espressif32.zip
|
||||
##platform = https://github.com/tasmota/platform-espressif32/releases/download/v.2.0.3/platform-espressif32-v.2.0.3.zip
|
||||
#build_flags = -Werror -Wall -Wno-deprecated-declarations -Wno-error=incompatible-pointer-types
|
||||
#board_build.f_cpu = 240000000L
|
||||
#lib_extra_dirs = ../../..
|
||||
#
|
||||
#[env:esp32s3]
|
||||
#board = esp32-s3-devkitc-1
|
||||
#framework = arduino
|
||||
#platform = https://github.com/tasmota/platform-espressif32/releases/download/2023.02.00/platform-espressif32.zip
|
||||
#build_flags = -Werror -Wall -Wno-deprecated-declarations -Wno-error=incompatible-pointer-types -Wno-error=unused-variable
|
||||
#board_build.f_cpu = 240000000L
|
||||
#lib_extra_dirs = ../../..
|
||||
#
|
||||
#[env:esp32c3]
|
||||
#board = esp32-c3-devkitm-1
|
||||
#framework = arduino
|
||||
#platform = espressif32
|
||||
##platform = https://github.com/tasmota/platform-espressif32/releases/download/2023.10.03/platform-espressif32.zip
|
||||
#build_flags = -Werror -Wall -Wno-deprecated-declarations -Wno-error=incompatible-pointer-types
|
||||
#board_build.f_cpu = 240000000L
|
||||
#lib_extra_dirs = ../../..
|
||||
#board_build.flash_mode = dio
|
||||
#upload_port = /dev/ttyACM0
|
||||
|
||||
[env:nanoatmega168]
|
||||
platform = atmelavr
|
||||
board = nanoatmega168
|
||||
framework = arduino
|
||||
build_flags = -Werror -Wall -Wno-deprecated-declarations
|
||||
lib_extra_dirs = ../../..
|
||||
|
||||
[env:nanoatmega328]
|
||||
platform = atmelavr
|
||||
board = nanoatmega328
|
||||
framework = arduino
|
||||
build_flags = -Werror -Wall -Wno-deprecated-declarations
|
||||
lib_extra_dirs = ../../..
|
||||
|
||||
[env:atmega2560]
|
||||
platform = atmelavr
|
||||
board = megaatmega2560
|
||||
framework = arduino
|
||||
build_flags = -Werror -Wall -Wno-deprecated-declarations
|
||||
lib_extra_dirs = ../../..
|
||||
|
||||
[env:atmelsam]
|
||||
platform = atmelsam
|
||||
board = due
|
||||
framework = arduino
|
||||
;build_flags = -Werror -Wall -Wno-deprecated-declarations
|
||||
; cannot use -Werror due to sam platform issue
|
||||
build_flags = -Wall -Wno-deprecated-declarations
|
||||
lib_extra_dirs = ../../..
|
||||
|
||||
[env:atmega32u4]
|
||||
platform = atmelavr
|
||||
board = leonardo
|
||||
framework = arduino
|
||||
build_flags = -Werror -Wall -Wno-deprecated-declarations -Wno-error=incompatible-pointer-types
|
||||
lib_extra_dirs = ../../..
|
||||
722
extras/doc/FastAccelStepper_API.md
Normal file
722
extras/doc/FastAccelStepper_API.md
Normal file
@@ -0,0 +1,722 @@
|
||||
# FastAccelStepper
|
||||
|
||||
FastAccelStepper is a high speed alternative for the
|
||||
[AccelStepper library](http:www.airspayce.com/mikem/arduino/AccelStepper/).
|
||||
Supported are avr (ATmega 168/328/P, ATmega2560), esp32 and atmelsam due.
|
||||
|
||||
Here is a basic example to run a stepper from position 0 to 1000 and back
|
||||
again to 0.
|
||||
```
|
||||
|
||||
FastAccelStepperEngine engine = FastAccelStepperEngine();
|
||||
FastAccelStepper *stepper = NULL;
|
||||
|
||||
#define dirPinStepper 5
|
||||
#define enablePinStepper 6
|
||||
#define stepPinStepper 9
|
||||
void setup() {
|
||||
engine.init();
|
||||
stepper = engine.stepperConnectToPin(stepPinStepper);
|
||||
if (stepper) {
|
||||
stepper->setDirectionPin(dirPinStepper);
|
||||
stepper->setEnablePin(enablePinStepper);
|
||||
stepper->setAutoEnable(true);
|
||||
|
||||
stepper->setSpeedInHz(500);
|
||||
stepper->setAcceleration(100);
|
||||
stepper->moveTo(1000, true);
|
||||
stepper->moveTo(0, true);
|
||||
}
|
||||
}
|
||||
|
||||
void loop() {}
|
||||
```
|
||||
|
||||
## FastAccelStepperEngine
|
||||
|
||||
This engine - actually a factory - provides you with instances of steppers.
|
||||
### Initialization
|
||||
|
||||
The FastAccelStepperEngine is declared with FastAccelStepperEngine().
|
||||
This is to occupy the needed memory.
|
||||
```cpp
|
||||
FastAccelStepperEngine engine = FastAccelStepperEngine();
|
||||
```
|
||||
But it still needs to be initialized.
|
||||
For this init shall be used:
|
||||
```cpp
|
||||
void setup() {
|
||||
engine.init();
|
||||
}
|
||||
```
|
||||
In a multitasking and multicore system like ESP32, the steppers are
|
||||
controlled by a continuously running task. This task can be fixed to one
|
||||
CPU core with this modified init()-call. ESP32 implementation detail: For
|
||||
values 0 and 1, xTaskCreatePinnedToCore() is used, or else xTaskCreate()
|
||||
```cpp
|
||||
void init(uint8_t cpu_core);
|
||||
#endif
|
||||
```
|
||||
### Creation of FastAccelStepper
|
||||
|
||||
Using a call to `stepperConnectToPin()` a FastAccelStepper instance is
|
||||
created. This call tells the stepper, which step pin to use. As the
|
||||
hardware may have limitations - e.g. no stepper resources anymore, or the
|
||||
step pin cannot be used, then NULL is returned. So it is advised to check
|
||||
the return value of this call.
|
||||
```cpp
|
||||
#if !defined(SUPPORT_SELECT_DRIVER_TYPE)
|
||||
FastAccelStepper* stepperConnectToPin(uint8_t step_pin);
|
||||
#endif
|
||||
```
|
||||
For e.g. esp32, there are two types of driver.
|
||||
One using mcpwm and pcnt module. And another using rmt module.
|
||||
This call allows to select the respective driver
|
||||
```cpp
|
||||
#if defined(SUPPORT_SELECT_DRIVER_TYPE)
|
||||
#define DRIVER_MCPWM_PCNT 0
|
||||
#define DRIVER_RMT 1
|
||||
#define DRIVER_DONT_CARE 2
|
||||
FastAccelStepper* stepperConnectToPin(uint8_t step_pin,
|
||||
uint8_t driver_type = DRIVER_DONT_CARE);
|
||||
#endif
|
||||
```
|
||||
Comments to valid pins:
|
||||
|
||||
| Device | Comment |
|
||||
|:----------------|:--------------------------------------------------------------------------------------------------|
|
||||
| ESP32 | Every output capable GPIO can be used |
|
||||
| ESP32S2 | Every output capable GPIO can be used |
|
||||
| Atmega168/328/p | Only the pins connected to OC1A and OC1B are allowed |
|
||||
| Atmega2560 | Only the pins connected to OC4A, OC4B and OC4C are allowed. |
|
||||
| Atmega32u4 | Only the pins connected to OC1A, OC1B and OC1C are allowed |
|
||||
| Atmel SAM | This can be one of each group of pins: 34/67/74/35, 17/36/72/37/42, 40/64/69/41, 9, 8/44, 7/45, 6 |
|
||||
## External Pins
|
||||
|
||||
If the direction/enable pins are e.g. connected via external HW (shift
|
||||
registers), then an external callback function can be supplied. The
|
||||
supplied value is either LOW or HIGH. The return value shall be the status
|
||||
of the pin (false for LOW or true for HIGH). If returned value and supplied
|
||||
value do not match, the stepper does not continue, but calls this function
|
||||
again.
|
||||
|
||||
This function is called from cyclic task/interrupt with 4ms rate, which
|
||||
creates the commands to put into the command queue. Thus the supplied
|
||||
function should take much less time than 4ms. Otherwise there is risk, that
|
||||
other running steppers are running out of commands in the queue. If this
|
||||
takes longer, then the function should be offloaded and return the new
|
||||
status, after the pin change has been successfully completed.
|
||||
|
||||
The callback has to be called on the FastAccelStepperEngine.
|
||||
See examples/ExternalCall
|
||||
|
||||
Stepperpins (enable or direction), which should use this external callback,
|
||||
need to be or'ed with PIN_EXTERNAL_FLAG ! FastAccelStepper uses this flag
|
||||
to determine, if a pin is external or internal.
|
||||
```cpp
|
||||
void setExternalCallForPin(bool (*func)(uint8_t pin, uint8_t value));
|
||||
```
|
||||
### Debug LED
|
||||
|
||||
If blinking of a LED is required to indicate, the stepper controller is
|
||||
still running, then the port. to which the LED is connected, can be told to
|
||||
the engine. The periodic task will let the associated LED blink with 1 Hz
|
||||
```cpp
|
||||
void setDebugLed(uint8_t ledPin);
|
||||
```
|
||||
### Return codes of calls to `move()` and `moveTo()`
|
||||
|
||||
The defined preprocessor macros are MOVE_xxx:
|
||||
MOVE_OK: All is OK:
|
||||
MOVE_ERR_NO_DIRECTION_PIN: Negative direction requested, but no direction pin
|
||||
MOVE_ERR_SPEED_IS_UNDEFINED: The maximum speed has not been set yet
|
||||
MOVE_ERR_ACCELERATION_IS_UNDEFINED: The acceleration to use has not been set
|
||||
yet
|
||||
### Return codes of `rampState()`
|
||||
|
||||
The return value is an uint8_t, which consist of two fields:
|
||||
|
||||
| Bit 7 | Bits 6-5 | Bits 4-0 |
|
||||
|:--------|:----------|:---------|
|
||||
|Always 0 | Direction | State |
|
||||
|
||||
The bit mask for direction and state:
|
||||
```cpp
|
||||
#define RAMP_DIRECTION_MASK (32 + 64)
|
||||
#define RAMP_STATE_MASK (1 + 2 + 4 + 8 + 16)
|
||||
```
|
||||
The defined ramp states are:
|
||||
```cpp
|
||||
#define RAMP_STATE_IDLE 0
|
||||
#define RAMP_STATE_COAST 1
|
||||
#define RAMP_STATE_ACCELERATE 2
|
||||
#define RAMP_STATE_DECELERATE 4
|
||||
#define RAMP_STATE_REVERSE (4 + 8)
|
||||
#define RAMP_STATE_ACCELERATING_FLAG 2
|
||||
#define RAMP_STATE_DECELERATING_FLAG 4
|
||||
```
|
||||
And the two directions of a move
|
||||
```cpp
|
||||
#define RAMP_DIRECTION_COUNT_UP 32
|
||||
#define RAMP_DIRECTION_COUNT_DOWN 64
|
||||
```
|
||||
A ramp state value of 2 is set after any move call on a stopped motor
|
||||
and until the stepper task is serviced. The stepper task will then
|
||||
control the direction flags
|
||||
|
||||
## Timing values - Architecture dependent
|
||||
|
||||
### AVR
|
||||
|VARIABLE | Value | Unit |
|
||||
|:----------------|------------:|:------------------------|
|
||||
|TICKS_PER_S | 16_000_000 | [ticks/s] |
|
||||
|MIN_CMD_TICKS | 640 | [1/TICKS_PER_S seconds] |
|
||||
|MIN_DIR_DELAY_US | 40 | [µs] |
|
||||
|MAX_DIR_DELAY_US | 4095 | [µs] |
|
||||
|
||||
### ESP32
|
||||
|VARIABLE | Value | Unit |
|
||||
|:----------------|------------:|:------------------------|
|
||||
|TICKS_PER_S | 16_000_000 | [ticks/s] |
|
||||
|MIN_CMD_TICKS | 3200 | [1/TICKS_PER_S seconds] |
|
||||
|MIN_DIR_DELAY_US | 200 | [µs] |
|
||||
|MAX_DIR_DELAY_US | 4095 | [µs] |
|
||||
|
||||
### SAM DUE
|
||||
|VARIABLE | Value | Unit |
|
||||
|:----------------|------------:|:------------------------|
|
||||
|TICKS_PER_S | 21_000_000 | [ticks/s] |
|
||||
|MIN_CMD_TICKS | 4200 | [1/TICKS_PER_S seconds] |
|
||||
|MIN_DIR_DELAY_US | 200 | [µs] |
|
||||
|MAX_DIR_DELAY_US | 3120 | [µs] |
|
||||
|
||||
# FastAccelStepper
|
||||
## Step Pin
|
||||
step pin is defined at creation. Here can retrieve the pin
|
||||
```cpp
|
||||
uint8_t getStepPin();
|
||||
```
|
||||
## Direction Pin
|
||||
if direction pin is connected, call this function.
|
||||
|
||||
If the pin number is >= 128, then the direction pin is assumed to be
|
||||
external and the external callback function (set by
|
||||
`setExternalCallForPin()`) is used to set the pin. For direction pin, this
|
||||
is implemented for esp32 and its supported derivates, and avr and its
|
||||
derivates except atmega32u4
|
||||
|
||||
For slow driver hardware the first step after any polarity change of the
|
||||
direction pin can be delayed by the value dir_change_delay_us. The allowed
|
||||
range is MIN_DIR_DELAY_US and MAX_DIR_DELAY_US. The special value of 0
|
||||
means, that no delay is added. Values 1 up to MIN_DIR_DELAY_US will be
|
||||
clamped to MIN_DIR_DELAY_US. Values above MAX_DIR_DELAY_US will be clamped
|
||||
to MAX_DIR_DELAY_US. For external pins, dir_change_delay_us is ignored,
|
||||
because the mechanism applied for external pins provides already pause
|
||||
in the range of ms or more.
|
||||
```cpp
|
||||
void setDirectionPin(uint8_t dirPin, bool dirHighCountsUp = true,
|
||||
uint16_t dir_change_delay_us = 0);
|
||||
uint8_t getDirectionPin() { return _dirPin; }
|
||||
bool directionPinHighCountsUp() { return _dirHighCountsUp; }
|
||||
```
|
||||
## Enable Pin
|
||||
if enable pin is connected, then use this function.
|
||||
|
||||
If the pin number is >= 128, then the enable pin is assumed to be
|
||||
external and the external callback function (set by
|
||||
`setExternalCallForPin()`) is used to set the pin.
|
||||
|
||||
In case there are two enable pins: one low and one high active, then
|
||||
these calls are valid and both pins will be operated:
|
||||
setEnablePin(pin1, true);
|
||||
setEnablePin(pin2, false);
|
||||
If pin1 and pin2 are same, then the last call will be used.
|
||||
```cpp
|
||||
void setEnablePin(uint8_t enablePin, bool low_active_enables_stepper = true);
|
||||
uint8_t getEnablePinHighActive() { return _enablePinHighActive; }
|
||||
uint8_t getEnablePinLowActive() { return _enablePinLowActive; }
|
||||
```
|
||||
using enableOutputs/disableOutputs the stepper can be enabled and disabled
|
||||
For a running motor with autoEnable set, disableOutputs() will return false
|
||||
bool enableOutputs();returns true, if enabled
|
||||
bool disableOutputs();returns true, if disabled
|
||||
In auto enable mode, the stepper is enabled before stepping and disabled
|
||||
afterwards. The delay from stepper enabled till first step and from
|
||||
last step to stepper disabled can be separately adjusted.
|
||||
The delay from enable to first step is done in ticks and as such is limited
|
||||
to MAX_ON_DELAY_TICKS, which translates approximately to 120ms for
|
||||
esp32 and 60ms for avr at 16 MHz). The delay till disable is done in period
|
||||
interrupt/task with 4 or 10 ms repetition rate and as such is with several
|
||||
ms jitter.
|
||||
```cpp
|
||||
void setAutoEnable(bool auto_enable);
|
||||
int8_t setDelayToEnable(uint32_t delay_us);
|
||||
void setDelayToDisable(uint16_t delay_ms);
|
||||
#define DELAY_OK 0
|
||||
#define DELAY_TOO_LOW -1
|
||||
#define DELAY_TOO_HIGH -2
|
||||
```
|
||||
## Stepper Position
|
||||
Retrieve the current position of the stepper
|
||||
|
||||
Comment for esp32 with rmt module:
|
||||
The actual position may be off by the number of steps in the ongoing
|
||||
command. If precise real time position is needed, attaching a pulse counter
|
||||
may be of help.
|
||||
```cpp
|
||||
int32_t getCurrentPosition();
|
||||
```
|
||||
Set the current position of the stepper - either in standstill or while
|
||||
moving.
|
||||
for esp32: the implementation uses getCurrentPosition(), which does not
|
||||
consider the steps of the current command
|
||||
=> recommend to use only in standstill
|
||||
```cpp
|
||||
void setCurrentPosition(int32_t new_pos);
|
||||
```
|
||||
## Stepper running status
|
||||
is true while the stepper is running or ramp generation is active
|
||||
```cpp
|
||||
bool isRunning();
|
||||
```
|
||||
## Speed
|
||||
For stepper movement control by FastAccelStepper's ramp generator
|
||||
|
||||
Speed can be defined in four different units:
|
||||
- In Hz: This means steps/s
|
||||
- In millHz: This means in steps/1000s
|
||||
- In us: This means in us/step
|
||||
|
||||
For the device's maximum allowed speed, the following calls can be used.
|
||||
```cpp
|
||||
uint16_t getMaxSpeedInUs();
|
||||
uint16_t getMaxSpeedInTicks();
|
||||
uint32_t getMaxSpeedInHz();
|
||||
uint32_t getMaxSpeedInMilliHz();
|
||||
```
|
||||
For esp32 and avr, the device's maximum allowed speed can be overridden.
|
||||
Allocating a new stepper will override any absolute speed limit.
|
||||
This is absolutely untested, no error checking implemented.
|
||||
Use at your own risk !
|
||||
```cpp
|
||||
#if SUPPORT_UNSAFE_ABS_SPEED_LIMIT_SETTING == 1
|
||||
void setAbsoluteSpeedLimit(uint16_t max_speed_in_ticks);
|
||||
#endif
|
||||
```
|
||||
Setting the speed can be done with the four `setSpeed...()` calls.
|
||||
The new value will be used only after call of these functions:
|
||||
|
||||
- `move()`
|
||||
- `moveTo()`
|
||||
- `runForward()`
|
||||
- `runBackward()`
|
||||
- `applySpeedAcceleration()`
|
||||
- `moveByAcceleration()`
|
||||
|
||||
Note: no update on `stopMove()`
|
||||
|
||||
Returns 0 on success, or -1 on invalid value.
|
||||
Invalid is faster than MaxSpeed or slower than ~250 Mio ticks/step.
|
||||
```cpp
|
||||
int8_t setSpeedInUs(uint32_t min_step_us);
|
||||
int8_t setSpeedInTicks(uint32_t min_step_ticks);
|
||||
int8_t setSpeedInHz(uint32_t speed_hz);
|
||||
int8_t setSpeedInMilliHz(uint32_t speed_mhz);
|
||||
```
|
||||
To retrieve current set speed. This means, while accelerating and/or
|
||||
decelerating, this is NOT the actual speed !
|
||||
```cpp
|
||||
uint32_t getSpeedInUs() { return _rg.getSpeedInUs(); }
|
||||
uint32_t getSpeedInTicks() { return _rg.getSpeedInTicks(); }
|
||||
uint32_t getSpeedInMilliHz() { return _rg.getSpeedInMilliHz(); }
|
||||
```
|
||||
If the current speed is needed, then use `getCurrentSpeed...()`. This
|
||||
retrieves the actual speed.
|
||||
|
||||
| value | description |
|
||||
|:-----:|:-----------------------------|
|
||||
| = 0 | while not moving |
|
||||
| > 0 | while position counting up |
|
||||
| < 0 | while position counting down |
|
||||
|
||||
If the parameter realtime is true, then the most actual speed
|
||||
from the stepper queue is derived. This works only, if the queue
|
||||
does not contain pauses, which is normally the case for slow speeds.
|
||||
Otherwise the speed from the ramp generator is reported, which is
|
||||
done always in case of `realtime == false`. That speed is typically
|
||||
the value of the speed a couple of milliseconds later.
|
||||
|
||||
The drawback of `realtime == true` is, that the reported speed
|
||||
may either come from the queue or from the ramp generator.
|
||||
This means the returned speed may have jumps during
|
||||
acceleration/deceleration.
|
||||
|
||||
For backward compatibility, the default is true.
|
||||
```cpp
|
||||
int32_t getCurrentSpeedInUs(bool realtime = true);
|
||||
int32_t getCurrentSpeedInMilliHz(bool realtime = true);
|
||||
```
|
||||
## Acceleration
|
||||
setAcceleration() expects as parameter the change of speed
|
||||
as step/s².
|
||||
If for example the speed should ramp up from 0 to 10000 steps/s within
|
||||
10s, then the acceleration is 10000 steps/s / 10s = 1000 steps/s²
|
||||
|
||||
New value will be used after call to
|
||||
move/moveTo/runForward/runBackward/applySpeedAcceleration/moveByAcceleration
|
||||
|
||||
note: no update on stopMove()
|
||||
|
||||
Returns 0 on success, or -1 on invalid value (<=0)
|
||||
```cpp
|
||||
int8_t setAcceleration(int32_t step_s_s) {
|
||||
return _rg.setAcceleration(step_s_s);
|
||||
}
|
||||
uint32_t getAcceleration() { return _rg.getAcceleration(); }
|
||||
```
|
||||
getCurrentAcceleration() retrieves the actual acceleration.
|
||||
= 0 while idle or coasting
|
||||
> 0 while speed is changing towards positive values
|
||||
< 0 while speed is changeing towards negative values
|
||||
```cpp
|
||||
int32_t getCurrentAcceleration() {
|
||||
return _rg.getCurrentAcceleration();
|
||||
}
|
||||
```
|
||||
## Linear Acceleration
|
||||
setLinearAcceleration expects as parameter the number of steps,
|
||||
where the acceleration is increased linearly from standstill up to the
|
||||
configured acceleration value. If this parameter is 0, then there will be
|
||||
no linear acceleration phase
|
||||
|
||||
If for example the acceleration should ramp up from 0 to 10000 steps/s^2
|
||||
within 100 steps, then call setLinearAcceleration(100)
|
||||
|
||||
The speed at which linear acceleration turns into constant acceleration
|
||||
can be calculated from the parameter linear_acceleration_steps.
|
||||
Let's call this parameter `s_h` for handover steps.
|
||||
Then the speed is:
|
||||
`v_h = sqrt(1.5 * a * s_h)`
|
||||
|
||||
New value will be used after call to
|
||||
move/moveTo/runForward/runBackward/applySpeedAcceleration/moveByAcceleration
|
||||
|
||||
note: no update on stopMove()
|
||||
```cpp
|
||||
void setLinearAcceleration(uint32_t linear_acceleration_steps) {
|
||||
_rg.setLinearAcceleration(linear_acceleration_steps);
|
||||
}
|
||||
```
|
||||
## Jump Start
|
||||
setJumpStart expects as parameter the ramp step to start from standstill.
|
||||
|
||||
The speed at which the stepper will start can be calculated like this:
|
||||
- If linear acceleration is not in use:
|
||||
start speed `v = sqrt(2 * a * jump_step)`
|
||||
- If linear acceleration is in use and `jump_step <= s_h`:
|
||||
start speed `v = sqrt(1.5*a)/s_h^(1/6) * jump_step^(2/3)`
|
||||
- If linear acceleration is in use and `jump_step > s_h`:
|
||||
start speed `v = sqrt(2 * a * (jump_step - s_h/4))`
|
||||
|
||||
|
||||
New value will be used after call to
|
||||
move/moveTo/runForward/runBackward
|
||||
```cpp
|
||||
void setJumpStart(uint32_t jump_step) { _rg.setJumpStart(jump_step); }
|
||||
```
|
||||
## Apply new speed/acceleration value
|
||||
This function applies new values for speed/acceleration.
|
||||
This is convenient especially, if the stepper is set to continuous running.
|
||||
```cpp
|
||||
void applySpeedAcceleration();
|
||||
```
|
||||
## Move commands
|
||||
### move() and moveTo()
|
||||
start/move the stepper for (move) steps or to an absolute position.
|
||||
|
||||
If the stepper is already running, then the current running move will be
|
||||
updated together with any updated values of acceleration/speed. The move is
|
||||
relative to the target position of any ongoing move ! If the new
|
||||
move/moveTo for an ongoing command would reverse the direction, then the
|
||||
command is silently ignored.
|
||||
return values are the MOVE_... constants
|
||||
```cpp
|
||||
int8_t move(int32_t move, bool blocking = false);
|
||||
int8_t moveTo(int32_t position, bool blocking = false);
|
||||
```
|
||||
### keepRunning()
|
||||
This command flags the stepper to keep run continuously into current
|
||||
direction. It can be stopped by stopMove.
|
||||
Be aware, if the motor is currently decelerating towards reversed
|
||||
direction, then keepRunning() will speed up again and not finish direction
|
||||
reversal first.
|
||||
```cpp
|
||||
void keepRunning();
|
||||
bool isRunningContinuously() { return _rg.isRunningContinuously(); }
|
||||
```
|
||||
### runForward() and runBackwards()
|
||||
These commands just let the motor run continuously in one direction.
|
||||
If the motor is running in the opposite direction, it will reverse
|
||||
return value as with move/moveTo
|
||||
```cpp
|
||||
int8_t runForward();
|
||||
int8_t runBackward();
|
||||
```
|
||||
### forwardStep() and backwardStep()
|
||||
forwardStep()/backwardstep() can be called, while stepper is not moving
|
||||
If stepper is moving, this is a no-op.
|
||||
backwardStep() is a no-op, if no direction pin defined
|
||||
It will immediately let the stepper perform one single step.
|
||||
If blocking = true, then the routine will wait till isRunning() is false
|
||||
```cpp
|
||||
void forwardStep(bool blocking = false);
|
||||
void backwardStep(bool blocking = false);
|
||||
```
|
||||
### moveByAcceleration()
|
||||
moveByAcceleration() can be called, if only the speed of the stepper
|
||||
is of interest and that speed to be controlled by acceleration.
|
||||
The maximum speed (in both directions) to be set by setSpeedInUs() before.
|
||||
The behaviour will be:
|
||||
acceleration > 0 => accelerate towards positive maximum speed
|
||||
acceleration = 0 => keep current speed
|
||||
acceleration < 0
|
||||
=> accelerate towards negative maximum speed if allow_reverse
|
||||
=> decelerate towards motor stop if allow_reverse = false
|
||||
return value as with move/moveTo
|
||||
```cpp
|
||||
int8_t moveByAcceleration(int32_t acceleration, bool allow_reverse = true);
|
||||
```
|
||||
### stopMove()
|
||||
Stop the running stepper with normal deceleration.
|
||||
This only sets a flag and can be called from an interrupt !
|
||||
```cpp
|
||||
void stopMove();
|
||||
bool isStopping() { return _rg.isStopping(); }
|
||||
```
|
||||
### stepsToStop()
|
||||
This returns the current step value of the ramp.
|
||||
This equals the number of steps for a motor to
|
||||
reach the current position and speed from standstill
|
||||
and to come to standstill with deceleration if stopped
|
||||
immediately.
|
||||
This value is valid with or without linear acceleration
|
||||
being used.
|
||||
Primary use is to forecast possible stop position.
|
||||
The stop position is:
|
||||
getCurrentPosition() + stepsToStop()
|
||||
in case of a motor running in positive direction.
|
||||
```cpp
|
||||
uint32_t stepsToStop() { return _rg.stepsToStop(); }
|
||||
```
|
||||
### forceStop()
|
||||
Abruptly stop the running stepper without deceleration.
|
||||
This can be called from an interrupt !
|
||||
|
||||
The stepper command queue will be processed, but no further commands are
|
||||
added. This means, that the stepper can be expected to stop within approx.
|
||||
20ms.
|
||||
```cpp
|
||||
void forceStop();
|
||||
```
|
||||
abruptly stop the running stepper without deceleration.
|
||||
This can be called from an interrupt !
|
||||
|
||||
No further step will be issued. As this is aborting all commands in the
|
||||
queue, the actual stop position is lost (recovering this position cannot be
|
||||
done within an interrupt). So the new position after stop has to be
|
||||
provided and will be set as current position after stop.
|
||||
```cpp
|
||||
void forceStopAndNewPosition(int32_t new_pos);
|
||||
```
|
||||
get the target position for the current move.
|
||||
As of now, this position is the view of the stepper task.
|
||||
This means, the value will stay unchanged after a move/moveTo until the
|
||||
stepper task is executed.
|
||||
In keep running mode, the targetPos() is not updated
|
||||
```cpp
|
||||
int32_t targetPos() { return _rg.targetPosition(); }
|
||||
```
|
||||
### Task planning
|
||||
The stepper task adds commands to the stepper queue until
|
||||
either at least two commands are planned, or the commands
|
||||
cover sufficient time into the future. Default value for that time is 20ms.
|
||||
|
||||
The stepper task is cyclically executed every ~4ms.
|
||||
Especially for avr, the step interrupts puts a significant load on the uC,
|
||||
so the cyclical stepper task can even run for 2-3 ms. On top of that,
|
||||
other interrupts caused by the application could increase the load even
|
||||
further.
|
||||
|
||||
Consequently, the forward planning should fill the queue for ideally two
|
||||
cycles, this means 8ms. This means, the default 20ms provide a sufficient
|
||||
margin and even a missed cycle is not an issue.
|
||||
|
||||
The drawback of the 20ms is, that any change in speed/acceleration are
|
||||
added after those 20ms and for an application, requiring fast reaction
|
||||
times, this may impact the expected performance.
|
||||
|
||||
Due to this the forward planning time can be adjusted with the following
|
||||
API call for each stepper individually.
|
||||
|
||||
Attention:
|
||||
- This is only for advanced users: no error checking is implemented.
|
||||
- Only change the forward planning time, if the stepper is not running.
|
||||
- Too small values bear the risk of a stepper running at full speed
|
||||
suddenly stopping
|
||||
due to lack of commands in the queue.
|
||||
```cpp
|
||||
void setForwardPlanningTimeInMs(uint8_t ms) {
|
||||
_forward_planning_in_ticks = ms;
|
||||
```
|
||||
_forward_planning_in_ticks *= TICKS_PER_S / 1000;ticks per ms
|
||||
```cpp
|
||||
}
|
||||
```
|
||||
## Low Level Stepper Queue Management (low level access)
|
||||
|
||||
If the queue is already running, then the start parameter is obsolote.
|
||||
But the queue may run out of commands while executing addQueueEntry,
|
||||
so it is better to set start=true to automatically restart/continue
|
||||
a running queue.
|
||||
|
||||
If the queue is not running, then the start parameter defines starting it
|
||||
or not. The latter case is of interest to first fill the queue and then
|
||||
start it.
|
||||
|
||||
The call addQueueEntry(NULL, true) just starts the queue. This is intended
|
||||
to achieve a near synchronous start of several steppers. Consequently it
|
||||
should be called with interrupts disabled and return very fast.
|
||||
Actually this is necessary, too, in case the queue is full and not
|
||||
started.
|
||||
```cpp
|
||||
int8_t addQueueEntry(const struct stepper_command_s* cmd, bool start = true);
|
||||
```
|
||||
Return codes for addQueueEntry
|
||||
positive values mean, that caller should retry later
|
||||
```cpp
|
||||
#define AQE_OK 0
|
||||
#define AQE_QUEUE_FULL 1
|
||||
#define AQE_DIR_PIN_IS_BUSY 2
|
||||
#define AQE_WAIT_FOR_ENABLE_PIN_ACTIVE 3
|
||||
#define AQE_DEVICE_NOT_READY 4
|
||||
#define AQE_ERROR_TICKS_TOO_LOW -1
|
||||
#define AQE_ERROR_EMPTY_QUEUE_TO_START -2
|
||||
#define AQE_ERROR_NO_DIR_PIN_TO_TOGGLE -3
|
||||
```
|
||||
### check functions for command queue being empty, full or running.
|
||||
```cpp
|
||||
bool isQueueEmpty();
|
||||
bool isQueueFull();
|
||||
bool isQueueRunning();
|
||||
```
|
||||
### functions to get the fill level of the queue
|
||||
|
||||
To retrieve the forward planning time in the queue, ticksInQueue()
|
||||
can be used. It sums up all ticks of the not yet processed commands.
|
||||
For commands defining pauses, the summed up value is entry.ticks.
|
||||
For commands with steps, the summed up value is entry.steps*entry.ticks
|
||||
```cpp
|
||||
uint32_t ticksInQueue();
|
||||
```
|
||||
This function can be used to check, if the commands in the queue
|
||||
will last for <min_ticks> ticks. This is again without the
|
||||
currently processed command.
|
||||
```cpp
|
||||
bool hasTicksInQueue(uint32_t min_ticks);
|
||||
```
|
||||
This function allows to check the number of commands in the queue.
|
||||
This is including the currently processed command.
|
||||
```cpp
|
||||
uint8_t queueEntries();
|
||||
```
|
||||
Get the future position of the stepper after all commands in queue are
|
||||
completed
|
||||
```cpp
|
||||
int32_t getPositionAfterCommandsCompleted();
|
||||
```
|
||||
Get the future speed of the stepper after all commands in queue are
|
||||
completed. This is in µs. Returns 0 for stopped motor
|
||||
|
||||
This value comes from the ramp generator and is not valid for raw command
|
||||
queue
|
||||
==> Will be renamed in future release
|
||||
```cpp
|
||||
uint32_t getPeriodInUsAfterCommandsCompleted();
|
||||
uint32_t getPeriodInTicksAfterCommandsCompleted();
|
||||
```
|
||||
Set the future position of the stepper after all commands in queue are
|
||||
completed. This has immediate effect to getCurrentPosition().
|
||||
```cpp
|
||||
void setPositionAfterCommandsCompleted(int32_t new_pos);
|
||||
```
|
||||
This function provides info, in which state the high level stepper control
|
||||
is operating. The return value is an `or` of RAMP_STATE_... and
|
||||
RAMP_DIRECTION_... flags. Definitions are above
|
||||
```cpp
|
||||
uint8_t rampState() { return _rg.rampState(); }
|
||||
```
|
||||
returns true, if the ramp generation is active
|
||||
```cpp
|
||||
bool isRampGeneratorActive() { return _rg.isRampGeneratorActive(); }
|
||||
```
|
||||
These functions allow to detach and reAttach a step pin for other use.
|
||||
Pretty low level, use with care or not at all
|
||||
```cpp
|
||||
void detachFromPin();
|
||||
void reAttachToPin();
|
||||
```
|
||||
## ESP32 only: Free pulse counter
|
||||
These four functions are only available on esp32.
|
||||
The first can attach any of the eight pulse counters to this stepper.
|
||||
The second then will read the current pulse counter value
|
||||
|
||||
The user is responsible to not use a pulse counter, which is occupied by a
|
||||
stepper and by this render the stepper or even blow up the uC.
|
||||
|
||||
Pulse counter 6 and 7 are not used by the stepper library and are judged as
|
||||
available. If only five steppers are defined, then 5 gets available. If
|
||||
four steppers are defined, then 4 is usable,too.
|
||||
|
||||
These functions are intended primarily for testing, because the library
|
||||
should always output the correct amount of pulses. Possible application
|
||||
usage would be an immediate and interrupt friendly version for
|
||||
getCurrentPosition()
|
||||
|
||||
The pulse counter counts up towards high_value.
|
||||
If the high_value is reached, then the pulse counter is reset to 0.
|
||||
Similarly, if direction pin is configured and set to count down,
|
||||
then the pulse counter counts towards low_value. When the low value is hit,
|
||||
the pulse counter is reset to 0.
|
||||
|
||||
If low_value and high_value are set to zero, then the pulse counter is just
|
||||
counting like any int16_t counter: 0...32767,-32768,-32767,...,0 and
|
||||
backwards accordingly
|
||||
|
||||
Possible application:
|
||||
Assume the stepper, to which the pulse counter attached to, needs 3200
|
||||
steps/revolution. If now attachToPulseCounter is called with -3200 and 3200
|
||||
for the low and high values respectively, then the momentary angle of the
|
||||
stepper (at exact this moment) can be retrieved just by reading the pulse
|
||||
counter. If the value is negative, then just add 3200.
|
||||
|
||||
Update for idf5 version:
|
||||
The pcnt_unit value is not used, because the available units are managed
|
||||
by the system. The parameter is kept for compatibility.
|
||||
|
||||
```cpp
|
||||
#if defined(SUPPORT_ESP32_PULSE_COUNTER) && (ESP_IDF_VERSION_MAJOR == 5)
|
||||
bool attachToPulseCounter(uint8_t unused_pcnt_unit = 0,
|
||||
int16_t low_value = -16384,
|
||||
int16_t high_value = 16384);
|
||||
int16_t readPulseCounter();
|
||||
void clearPulseCounter();
|
||||
bool pulseCounterAttached() { return _attached_pulse_unit != NULL; }
|
||||
#endif
|
||||
#if defined(SUPPORT_ESP32_PULSE_COUNTER) && (ESP_IDF_VERSION_MAJOR == 4)
|
||||
bool attachToPulseCounter(uint8_t pcnt_unit, int16_t low_value = -16384,
|
||||
int16_t high_value = 16384);
|
||||
int16_t readPulseCounter();
|
||||
void clearPulseCounter();
|
||||
bool pulseCounterAttached() { return _attached_pulse_cnt_unit >= 0; }
|
||||
#endif
|
||||
```
|
||||
44
extras/doc/application.wxm
Normal file
44
extras/doc/application.wxm
Normal file
@@ -0,0 +1,44 @@
|
||||
/* [wxMaxima batch file version 1] [ DO NOT EDIT BY HAND! ]*/
|
||||
/* [ Created with wxMaxima version 21.11.0 ] */
|
||||
/* [wxMaxima: input start ] */
|
||||
/*
|
||||
With the parameters a_ref and T² and the function f with derivatives and inverses, the formulas are:
|
||||
*/
|
||||
s_max = a_ref * T²;
|
||||
t = T * f_inv(s / s_max);
|
||||
s(t,T) := s_max * f(t/T);
|
||||
v(s,T) := s_max / T * (1 / f_inv_1(s / s_max));
|
||||
p(s,T) := T / s_max * f_inv_1(s / s_max);
|
||||
a(t,T) := a_ref * f_2(t/T);
|
||||
/* [wxMaxima: input end ] */
|
||||
|
||||
|
||||
/* [wxMaxima: input start ] */
|
||||
/*
|
||||
It is important, that f_inv_1(x) can be calculated stable for x<<<1 over several decades well.
|
||||
|
||||
Due to this a segmental definition could be useful.
|
||||
For example x³ and cubic root can be calculated easily for several decades close to 0.
|
||||
*/
|
||||
a:0.5 $
|
||||
b:1.46 $
|
||||
select(x) := x < a $
|
||||
seg1(x) :=1.295* x^3 $
|
||||
seg2(x) := 1-(1-seg1(a))*sin((1-x)*%pi/b)/sin((1-a)*%pi/b) $
|
||||
seg1_1(x):=diff(seg1(x),x)$
|
||||
seg2_1(x):=diff(seg2(x),x)$
|
||||
seg1_2(x):=diff(seg1(x),x,2)$
|
||||
seg2_2(x):=diff(seg2(x),x,2)$
|
||||
f(x) := if select(x) then seg1(x) else seg2(x) $
|
||||
[seg1_1(x),seg2_1(x)];wxplot2d([f(x),%[1],%[2]],[x,0,1]);
|
||||
/* [wxMaxima: input end ] */
|
||||
|
||||
|
||||
/* [wxMaxima: input start ] */
|
||||
[seg1_2(x),seg2_2(x)];wxplot2d([%[1],%[2]],[x,0,1]);
|
||||
/* [wxMaxima: input end ] */
|
||||
|
||||
|
||||
|
||||
/* Old versions of Maxima abort on loading files that end in a comment. */
|
||||
"Created with wxMaxima 21.11.0"$
|
||||
62
extras/doc/arch_esp32.txt
Normal file
62
extras/doc/arch_esp32.txt
Normal file
@@ -0,0 +1,62 @@
|
||||
StepperISR_esp32.cpp
|
||||
|
||||
The driver makes use of mcpwm module(s) and pcnt modules.
|
||||
The mcpwm generates the timing of the pulses.
|
||||
The pcnt module counts fast pulses.
|
||||
|
||||
The io-matrix of esp32 is configured, that the mcpwm generated
|
||||
pulses are routed to the GPIO pad and those pulses are
|
||||
fed back into the pulse counter.
|
||||
|
||||
If the command queue contains a command with 0 steps aka pause,
|
||||
then there is nothing to count and thus the mcpwm module interrupt
|
||||
is enabled. Otherwise the mcpwm module interrupt is disabled
|
||||
and the a pcnt interrupt is generated, when the number of steps is completed.
|
||||
|
||||
Thereof the interrupt rate is max(n,1)*p ticks,
|
||||
where n is the number of steps and p the ticks - as defined in the command.
|
||||
|
||||
Timing:
|
||||
|
||||
For steps = 0: ===========================================================================
|
||||
|
||||
Timer 0 1 2 3 4 ... ticks-1 ticks ticks-1 ... 1 0 1 2 3
|
||||
TEA X X X
|
||||
TEP X
|
||||
STEP 0 0 0 0 0 0 0 0 0 ...
|
||||
PWMint |---| (|-----|) in case of another pause
|
||||
PCNTint
|
||||
|
||||
Only PWM interrupt is triggered on time == 1. On down counting, a second event is generated two clock cycles later: too fast for two interrupts.
|
||||
|
||||
|
||||
For steps = 1: ===========================================================================
|
||||
|
||||
Timer 0 1 2 3 4 ... ticks-1 ticks ticks-1 ... 1 0 1 2 3
|
||||
CMPA X X
|
||||
TEP X
|
||||
STEP 0 1 1 1 1 1 0 0 0.....
|
||||
PCNT 0 1 1 1 1 ............................
|
||||
PWMint
|
||||
PCNTint |---|
|
||||
|
||||
PCNT interrupt is triggered on time == 1.
|
||||
On time == 1, the step output is triggered high and transition to 0 on ticks
|
||||
|
||||
For steps = 2 ===========================================================================
|
||||
|
||||
Timer 0 1 2 3 4 ... ticks ... 1 0 1 2 3...ticks ... 1 0
|
||||
CMPA X X
|
||||
TEP X X
|
||||
STEP 0 1 1 1 1 0 0 0 1 1 1... 0 0 0...
|
||||
PCNT 0 1 1 1 1 1 1 1 2 2 2...
|
||||
PWMint
|
||||
PCNTint |---|
|
||||
|
||||
PCNT interrupt is triggered on time == 1 and counter value 2.
|
||||
|
||||
Important: mcpwm update method at TEZ
|
||||
|
||||
Consequently: The ticks wait time is AFTER the pulse and started from L->H transition.
|
||||
Thus the pulse of the following command starts after this command's period
|
||||
|
||||
338
extras/doc/generalization.wxm
Normal file
338
extras/doc/generalization.wxm
Normal file
@@ -0,0 +1,338 @@
|
||||
/* [wxMaxima batch file version 1] [ DO NOT EDIT BY HAND! ]*/
|
||||
/* [ Created with wxMaxima version 21.11.0 ] */
|
||||
/* [wxMaxima: input start ] */
|
||||
/*
|
||||
For a constant acceleration ramp the steps and speed at time t can be calculated by:
|
||||
*/
|
||||
s(t,a) := 1/2 * a * t^2;
|
||||
v(t,a) := a * t;
|
||||
/* [wxMaxima: input end ] */
|
||||
|
||||
|
||||
/* [wxMaxima: input start ] */
|
||||
/*
|
||||
The time at a given step is then
|
||||
*/
|
||||
t(s,a) := sqrt(2 * s / a);
|
||||
/* [wxMaxima: input end ] */
|
||||
|
||||
|
||||
/* [wxMaxima: input start ] */
|
||||
/*
|
||||
and the speed at a given step is then
|
||||
*/
|
||||
v(s,a) := sqrt(2 * s * a);
|
||||
/* [wxMaxima: input end ] */
|
||||
|
||||
|
||||
/* [wxMaxima: input start ] */
|
||||
/*
|
||||
and finally the step rate R (time distance between two pulses):
|
||||
*/
|
||||
R(s,a) := 1 / sqrt(2 * s * a);
|
||||
/* [wxMaxima: input end ] */
|
||||
|
||||
|
||||
/* [wxMaxima: input start ] */
|
||||
/*
|
||||
With s_ramp being the number of steps to accelerate or decelerate and s_total being the number of the steps for the total ramp including acceleration and deceleration, the complete ramp with acceleration, coasting and deceleration can be written as
|
||||
*/
|
||||
v(s,a, s_ramp, s_total) := if s < s_ramp then sqrt(2 * s * a) else if s < s_total-s_ramp then sqrt(2 * s_ramp * a) else if s < s_total then sqrt(2 * (s_total-s) * a) else 0 $
|
||||
/* [wxMaxima: input end ] */
|
||||
|
||||
|
||||
/* [wxMaxima: input start ] */
|
||||
/*
|
||||
And the acceleration over steps is simply
|
||||
*/
|
||||
a(s,a, s_ramp, s_total) := if s < s_ramp then a else if s < s_total-s_ramp then 0 else if s < s_total then -a else 0 $
|
||||
/* [wxMaxima: input end ] */
|
||||
|
||||
|
||||
/* [wxMaxima: input start ] */
|
||||
/*
|
||||
As an example the acceleration over steps for acceleration = 5 m/s², ramp steps = 100 and total ramp steps = 1000:
|
||||
*/
|
||||
wxplot2d([a(s,5,100,1000)],[s,0,1000]);
|
||||
/* [wxMaxima: input end ] */
|
||||
|
||||
|
||||
/* [wxMaxima: input start ] */
|
||||
wxplot2d([v(s,5,100,1000)],[s,0,1000]);
|
||||
/* [wxMaxima: input end ] */
|
||||
|
||||
|
||||
/* [wxMaxima: input start ] */
|
||||
/*
|
||||
In order to generalize the ramp function, we introduce a dimensionless function f, which translates from range [0,1] into the range [0,1].
|
||||
*/
|
||||
v(s) := v_max * f(s/s_ramp);
|
||||
/* [wxMaxima: input end ] */
|
||||
|
||||
|
||||
/* [wxMaxima: input start ] */
|
||||
/*
|
||||
The first derivate of v aka v_1 is with df/fx = f_1:
|
||||
*/
|
||||
v_1(s) := v_max/s_ramp * f_1(s/s_ramp);
|
||||
/* [wxMaxima: input end ] */
|
||||
|
||||
|
||||
/* [wxMaxima: input start ] */
|
||||
/*
|
||||
Using this definition, the acceleration a(s) can be approximated at steps s:
|
||||
*/
|
||||
a(s) := v_1(s) * v(s);
|
||||
/* [wxMaxima: input end ] */
|
||||
|
||||
|
||||
/* [wxMaxima: input start ] */
|
||||
/*
|
||||
With these two functions a(s) is:
|
||||
*/
|
||||
a(s);
|
||||
/* [wxMaxima: input end ] */
|
||||
|
||||
|
||||
/* [wxMaxima: input start ] */
|
||||
/*
|
||||
Now we need a mathematical function, which can be used to define a smooth acceleration ramp without jumps.
|
||||
tanh(x) poses problem for the x-range. The smoothstep function starts at x=0 too slow. As we are controlling the speed,
|
||||
we already get one factor of x. So idea is to have a function coming out linearly from x with a maximum at x=1.
|
||||
|
||||
This time sine function with its first derivative to be used:
|
||||
*/
|
||||
f(x) := sin(x * %pi/2);
|
||||
diff(f(x),x);
|
||||
/* [wxMaxima: input end ] */
|
||||
|
||||
|
||||
/* [wxMaxima: input start ] */
|
||||
/*
|
||||
So the first derivative is simply
|
||||
*/
|
||||
f_1(x) :=%pi*cos(%pi*x/2)/2;
|
||||
/* [wxMaxima: input end ] */
|
||||
|
||||
|
||||
/* [wxMaxima: input start ] */
|
||||
/*
|
||||
Drawn over the x-range from 0 to 1:
|
||||
*/
|
||||
wxplot2d([f(x),f_1(x)],[x,0,1]);
|
||||
/* [wxMaxima: input end ] */
|
||||
|
||||
|
||||
/* [wxMaxima: input start ] */
|
||||
/*
|
||||
How does this apply to our functions v and a as dependent from step s ?
|
||||
*/
|
||||
fundef(v); fundef(a);
|
||||
/* [wxMaxima: input end ] */
|
||||
|
||||
|
||||
/* [wxMaxima: input start ] */
|
||||
/*
|
||||
With this the function to calculate the acceleration is (with constant factors eliminated):
|
||||
*/
|
||||
expand(a(s));
|
||||
/* [wxMaxima: input end ] */
|
||||
|
||||
|
||||
/* [wxMaxima: input start ] */
|
||||
/*
|
||||
The shape of a(s) is:
|
||||
*/
|
||||
wxplot2d([f(x)*f_1(x)],[x,0,1]);
|
||||
/* [wxMaxima: input end ] */
|
||||
|
||||
|
||||
/* [wxMaxima: input start ] */
|
||||
/*
|
||||
The maximum of this function is c at x_c
|
||||
*/
|
||||
x_c : 0.5;
|
||||
c : f(x_c)*f_1(x_c);
|
||||
/* [wxMaxima: input end ] */
|
||||
|
||||
|
||||
/* [wxMaxima: input start ] */
|
||||
/*
|
||||
The maximum value of the function is pi/4
|
||||
*/
|
||||
float(c);float(%pi/4);
|
||||
/* [wxMaxima: input end ] */
|
||||
|
||||
|
||||
/* [wxMaxima: input start ] */
|
||||
/*
|
||||
Consequently the maximum acceleration is:
|
||||
*/
|
||||
a_max = v_max² / s_ramp * %pi/4;
|
||||
|
||||
/* [wxMaxima: input end ] */
|
||||
|
||||
|
||||
/* [wxMaxima: input start ] */
|
||||
/*
|
||||
In FastAccelStepper maximum acceleration and maximum speed are configured, so this equation can be used to determine s_ramp.
|
||||
*/
|
||||
ref: s_ramp = %pi/4 * v_max² / a_max;
|
||||
/* [wxMaxima: input end ] */
|
||||
|
||||
|
||||
/* [wxMaxima: input start ] */
|
||||
/*
|
||||
The speed at step s = 1 is:
|
||||
*/
|
||||
ev(v(s), s=1,ref);
|
||||
/* [wxMaxima: input end ] */
|
||||
|
||||
|
||||
/* [wxMaxima: input start ] */
|
||||
/*
|
||||
As sin(x) ~ x for x << 1 the speed at step s=1 is:
|
||||
*/
|
||||
2*a_max/v_max;
|
||||
/* [wxMaxima: input end ] */
|
||||
|
||||
|
||||
/* [wxMaxima: input start ] */
|
||||
/*
|
||||
For reference: with constant acceleration the speed at step s=1 is independent of v_max
|
||||
*/
|
||||
v = sqrt(2*a);
|
||||
/* [wxMaxima: input end ] */
|
||||
|
||||
|
||||
/* [wxMaxima: input start ] */
|
||||
/*
|
||||
The issue is, that the relation v(s) in this manner cannot be applied, if the speed shall change from v_max to -v_max. In this scenario, the acceleration at v = 0 aka the turn point shall be at maximum during deceleration/acceleration phase.
|
||||
|
||||
Second problem is an adequate forecast, if at turnpoint the acceleration needs to be reduced in order to not overshoot the targetted speed.
|
||||
*/;
|
||||
/* [wxMaxima: input end ] */
|
||||
|
||||
|
||||
/* [wxMaxima: input start ] */
|
||||
/*
|
||||
From application point of view, it is better to define acceleration as dependent of time and mathematically being a second derivative:
|
||||
*/
|
||||
a(t,T) := a_ref * f_2(t/T);
|
||||
/* [wxMaxima: input end ] */
|
||||
|
||||
|
||||
/* [wxMaxima: input start ] */
|
||||
/*
|
||||
Using this approach speed and distance can be deducted easily:
|
||||
*/
|
||||
v(t,T) := T * a_ref * f_1(t/T);
|
||||
s(t,T) := T² * a_ref * f(t/T);
|
||||
/* [wxMaxima: input end ] */
|
||||
|
||||
|
||||
/* [wxMaxima: input start ] */
|
||||
/*
|
||||
with f_inv(x) = y as solution for f(y) = x, time can be derived as dependent of distance:
|
||||
*/
|
||||
t = T * f_inv(s / (a_ref*T²));
|
||||
/* [wxMaxima: input end ] */
|
||||
|
||||
|
||||
/* [wxMaxima: input start ] */
|
||||
/*
|
||||
Using this approach v(t,T) can be stated as dependent of s:
|
||||
*/
|
||||
v(s,T) := T * a_ref * f_1(f_inv(s / (a_ref*T²)));
|
||||
/* [wxMaxima: input end ] */
|
||||
|
||||
|
||||
/* [wxMaxima: input start ] */
|
||||
/*
|
||||
Analyzing the first derivative as function of its inverse:
|
||||
*/
|
||||
F_1(F_inv(y)) = d/dx * F(x = F_inv(y)) ;
|
||||
/* [wxMaxima: input end ] */
|
||||
|
||||
|
||||
/* [wxMaxima: input start ] */
|
||||
F_1(F_inv(y)) = d/dy * dy/dx* F(x = F_inv(y)) $
|
||||
d/dy * F(x = F_inv(y)) = 1 $
|
||||
F_1(F_inv(y)) = dy/dx $
|
||||
F_1(F_inv(y)) = 1/F_inv_1(y) ;
|
||||
/* [wxMaxima: input end ] */
|
||||
|
||||
|
||||
/* [wxMaxima: input start ] */
|
||||
/*
|
||||
Applied to v(s,T):
|
||||
*/
|
||||
v(s,T) := T * a_ref / f_inv_1(s / (a_ref*T²));
|
||||
/* [wxMaxima: input end ] */
|
||||
|
||||
|
||||
/* [wxMaxima: input start ] */
|
||||
/*
|
||||
And for the period being 1/v:
|
||||
*/
|
||||
p(s,T) := f_inv_1(s / (a_ref*T²)) / (T*a_ref);
|
||||
/* [wxMaxima: input end ] */
|
||||
|
||||
|
||||
/* [wxMaxima: input start ] */
|
||||
/*
|
||||
Using s_max = a_ref * T² this can be rewritten to:
|
||||
*/
|
||||
p(s,T) := T / s_max * f_inv_1(s / s_max);
|
||||
/* [wxMaxima: input end ] */
|
||||
|
||||
|
||||
/* [wxMaxima: input start ] */
|
||||
/*
|
||||
cross check with constant acceleration. => OK
|
||||
*/
|
||||
f_2(x) = 1;
|
||||
f(x) = x²/2;
|
||||
f_inv(x) = sqrt(2*x);
|
||||
f_inv_1(x) = 1/sqrt(2*x);
|
||||
p(s,T) := 1/sqrt(2*s/a_ref/T²)/(T*a_ref) $
|
||||
p(s,T) := sqrt(a_ref*T²)/sqrt(2*s)/(T*a_ref) $
|
||||
p(s,T) := 1/sqrt(2*s *a_ref);
|
||||
/* [wxMaxima: input end ] */
|
||||
|
||||
|
||||
/* [wxMaxima: input start ] */
|
||||
/*
|
||||
as the math is ok. So try the sine function for ramp up of the speed
|
||||
*/
|
||||
f(x) := sin(x*%pi/2);
|
||||
wxplot2d([f(x)],[x,0,1]);
|
||||
/* [wxMaxima: input end ] */
|
||||
|
||||
|
||||
/* [wxMaxima: input start ] */
|
||||
solve(y=f(x),x);
|
||||
/* [wxMaxima: input end ] */
|
||||
|
||||
|
||||
/* [wxMaxima: input start ] */
|
||||
diff(rhs(%[1]),y);
|
||||
/* [wxMaxima: input end ] */
|
||||
|
||||
|
||||
/* [wxMaxima: input start ] */
|
||||
wxplot2d([%],[y,0.1,0.9]);
|
||||
/* [wxMaxima: input end ] */
|
||||
|
||||
|
||||
/* [wxMaxima: input start ] */
|
||||
/*
|
||||
Looks ok, too. Just the cosine will generate maximum acceleration at ramp start and end. So another function is needed.
|
||||
The smoothstep function would be interesting, but the inverse is algebraically very complex.
|
||||
*/
|
||||
/* [wxMaxima: input end ] */
|
||||
|
||||
|
||||
|
||||
/* Old versions of Maxima abort on loading files that end in a comment. */
|
||||
"Created with wxMaxima 21.11.0"$
|
||||
125
extras/doc/ramp.md
Normal file
125
extras/doc/ramp.md
Normal file
@@ -0,0 +1,125 @@
|
||||
# Ramp generator
|
||||
|
||||
# Introduction
|
||||
|
||||
The ramp generator increases the speed linearly with the acceleration.
|
||||
If e.g. a=1000 steps/s², then after 1s the speed is 1000 steps/s.
|
||||
|
||||
The full ramp consists of three phases: acceleration+coasting+deceleration.
|
||||
If the number of steps are less than the required steps for acceleration and deceleration, then there will not be any coasting phase.
|
||||
|
||||
For illustration here an ascii chart of the ramp
|
||||
|
||||
```
|
||||
Speed
|
||||
| -------------------
|
||||
| / \
|
||||
| / \
|
||||
| / \
|
||||
0---/ \------
|
||||
|<->|<--------------->|<->|
|
||||
Ta Tc Td
|
||||
-----------------------------------> Time
|
||||
|
||||
Ta ... acceleration time.
|
||||
Tc ... coasting time.
|
||||
Td ... deceleration time.
|
||||
```
|
||||
|
||||
The total ramp time is Ta + Tc + Td = T
|
||||
|
||||
Due to acceleration = deceleration, the related times Ta and Td are same.
|
||||
$$
|
||||
T=2*Ta+Tc
|
||||
$$
|
||||
|
||||
The steps executed in coasting are simply:
|
||||
$$
|
||||
steps_{coasting} = v * Tc
|
||||
$$
|
||||
|
||||
The steps executed during acceleration and deceleration are:
|
||||
$$
|
||||
steps_{acceleration} = 0.5 * a * Ta²
|
||||
$$
|
||||
|
||||
The total steps are:
|
||||
$$
|
||||
\begin{align}
|
||||
steps &= steps_{acceleration} + steps_{coasting} + steps_{deceleration} \\
|
||||
&= 2 * steps_{acceleration} + steps_{coasting} \\
|
||||
&= a * Ta² + v * Tc \\
|
||||
&= a * Ta² + (a * Ta) * Tc \\
|
||||
&= a * Ta * (Ta + Tc) \\
|
||||
&= a * Ta * (T - Ta)
|
||||
\end{align}
|
||||
$$
|
||||
This can be rearranged to calculate the required acceleration to perform `steps` during the total ramp time T and acceleration time Ta:
|
||||
$$
|
||||
a = \frac{steps}{ Ta * (T - Ta) }
|
||||
$$
|
||||
|
||||
# Calculation example
|
||||
|
||||
The stepper motor should perform 32000 steps in 10s.
|
||||
|
||||
The required acceleration and speed for different acceleration times are calculated as this:
|
||||
$$
|
||||
\begin{align}
|
||||
Ta = 1s => a &= \frac{32000}{1 * 9} steps/s² = 3556 steps/s² \\
|
||||
v &= a*Ta = 3556 steps/s => 281us/step \\
|
||||
Ta = 2s => a &= \frac{32000}{2 * 8} steps/s² = 2000 steps/s² \\
|
||||
v &= a*Ta = 4000 steps/s => 250us/step \\
|
||||
Ta = 3s => a &= \frac{32000}{3 * 7} steps/s² = 1524 steps/s² \\
|
||||
v &= a*Ta = 4571 steps/s => 218us/step \\
|
||||
Ta = 4s => a &= \frac{32000}{4 * 6} steps/s² = 1333 steps/s² \\
|
||||
v &= a*Ta = 5333 steps/s => 188us/step \\
|
||||
Ta = 5s => a &= \frac{32000}{5 * 5} steps/s² = 1280 steps/s² \\
|
||||
v &= a*Ta = 6400 steps/s => 156us/step
|
||||
\end{align}
|
||||
$$
|
||||
|
||||
As commands for the StepperDemo:
|
||||
```
|
||||
M1 A3556 V281 R32000
|
||||
M1 A2000 V250 R32000
|
||||
M1 A1524 V218 R32000
|
||||
M1 A1333 V188 R32000
|
||||
M1 A1280 V156 R32000
|
||||
```
|
||||
|
||||
# Special case
|
||||
|
||||
The minimum command time for a bundle of steps is `MIN_CMD_TICKS`. The ramp generator need to make sure,
|
||||
that any command issued to the command queue meets this requirement.
|
||||
|
||||
With high acceleration this can get problematic coming from or going to stand still.
|
||||
|
||||
The required condition to meet this requirement is:
|
||||
$$
|
||||
steps * \frac{1}{v} \ge T_{CMD}
|
||||
$$
|
||||
|
||||
From stand still the speed after `MIN_CMD_TICKS`is:
|
||||
$$
|
||||
v_{start} = a * T_{CMD}
|
||||
$$
|
||||
|
||||
So the related condition for steps is:
|
||||
$$
|
||||
\begin{align}
|
||||
steps * \frac{1}{a * T_{CMD}} &\ge T_{CMD} \\
|
||||
steps &\ge a * T_{CMD}^2
|
||||
\end{align}
|
||||
$$
|
||||
|
||||
Based on this there can be deducted two problems:
|
||||
|
||||
1. Any move command with less steps cannot be fulfilled with this acceleration
|
||||
|
||||
=> Remedy: Run these steps at maximum allowed speed based on `MIN_CMD_TICKS`
|
||||
|
||||
2. While ramping down the last issued command may violate this condition
|
||||
|
||||
=> Remedy: Run these steps at maximum allowed speed based on `MIN_CMD_TICKS`.
|
||||
The problem is to distinguish this case from a legitimate overshoot situation.
|
||||
63
extras/doc/ramp_cubic_quadratic.md
Normal file
63
extras/doc/ramp_cubic_quadratic.md
Normal file
@@ -0,0 +1,63 @@
|
||||
# Ramp generator concept for cubic/quadratic ramp combination
|
||||
|
||||
Piecewise ramp:
|
||||
- ramp up with s = 1/6 * j * t^3 and v = 1/2 * j * t^2
|
||||
so t = sqrt(2*v/j) and s = 1/6 * j * (2*v/j)^(3/2)
|
||||
and (6*s/j)^(2/3) = 2*v / j
|
||||
and v = j/2 * (6/j)^(2/3) * s^(2/3) = 6^(2/3)/2 * j^(1/3) * s^(2/3)
|
||||
- define hand over point s_h
|
||||
- ramp up to max speed with s = 1/2 * a * t'^2 = 1/2 * v^2 / a
|
||||
|
||||
Conditions at hand over point s_h:
|
||||
- s_h = 1/6 * j * t_h^3 = 1/2 * a * t'_h^2 + ds
|
||||
- v_h = 1/2 * j * t_h^2 = a * t'_h
|
||||
- a_h = j * t_h = a
|
||||
|
||||
Replacing j = a / t_h:
|
||||
- s_h = 1/6 * a * t_h^2 = 1/2 * a * t'_h^2 + ds
|
||||
- v_h = 1/2 * a * t_h = a * t'_h
|
||||
|
||||
With t'_h = t_h - dt:
|
||||
- s_h = 1/6 * a * t_h^2 = 1/2 * a * (t_h^2 - 2*t_h*dt + dt^2) + ds
|
||||
- v_h = 1/2 * a * t_h = a * t_h - a * dt
|
||||
|
||||
Consequently from v_h:
|
||||
dt = th/2
|
||||
|
||||
And for s:
|
||||
- s_h = 1/6 * a * t_h^2 = 1/8 * a * t_h^2 + ds
|
||||
|
||||
So ds:
|
||||
ds = (8-6)/48 * a * t_h^2 = 1/24 * a * t_h^2 = s_h/4
|
||||
|
||||
So we have clear relation from s to the ramp speed:
|
||||
|
||||
if s < s_h, then cubic ramp: v(s) = 6^(2/3)/2 * j^(1/3) * s^(2/3)
|
||||
if s >= s_h, then quadratic ramp: v(s) = sqrt(2 * a * (s-s_h/4))
|
||||
|
||||
Still need to reduce j and s_h to one parameter of freedom.
|
||||
If choose s_h as user defined parameter, then:
|
||||
|
||||
t_h = sqrt(6 * s_h / a)
|
||||
|
||||
and so:
|
||||
|
||||
j = a / t_h = a / sqrt(6 * s_h / a) = sqrt(a^3 / (6 * s_h))
|
||||
|
||||
For the speed calculation cubic ramp, this yields:
|
||||
|
||||
v(s) = [6^(2/3)/2 * (a^3/6/s_h)^(1/6)] * s^(2/3)
|
||||
= [6^(4/6)/2 * (a^3)^(1/6) * 6^(-1/6) * s_h^(-1/6)] * s^(2/3)
|
||||
= [6^(3/6)/2 * sqrt(a) * s_h^(-1/6)] * s^(2/3)
|
||||
= [sqrt(6)/2 * sqrt(a) * s_h^(-1/6)] * s^(2/3)
|
||||
= [sqrt(3/2) * sqrt(a) / s_h^(1/6) ] * s^(2/3)
|
||||
|
||||
Check cubic:
|
||||
v(s_h) = [sqrt(3/2) * sqrt(a) / s_h^(1/6) ] * s_h^(2/3)
|
||||
= [sqrt(3/2) * sqrt(a) ] * s_h^(1/2)
|
||||
|
||||
and quadratic:
|
||||
v(s_h) = sqrt(2 * a * s_h * 3 / 4) = sqrt(3/2 * a * s_h) equals cubic
|
||||
|
||||
With s_h = 0 there will be no cubic ramp start.
|
||||
|
||||
17
extras/gen_pmf_const/Makefile
Normal file
17
extras/gen_pmf_const/Makefile
Normal file
@@ -0,0 +1,17 @@
|
||||
CPPFLAGS=-I../../src
|
||||
|
||||
../../src/PoorManFloatConst.h: main
|
||||
./main >../../src/PoorManFloatConst.h
|
||||
|
||||
main: main.o PoorManFloat.o
|
||||
|
||||
main.o: main.cpp
|
||||
|
||||
PoorManFloat.o: PoorManFloat.cpp
|
||||
|
||||
PoorManFloat.cpp: ../../src/PoorManFloat.cpp
|
||||
cp ../../src/PoorManFloat.cpp PoorManFloat.cpp
|
||||
|
||||
clean:
|
||||
rm -f PoorManFloat.cpp
|
||||
rm -f main main.o PoorManFloat.o
|
||||
4
extras/gen_pmf_const/README.md
Normal file
4
extras/gen_pmf_const/README.md
Normal file
@@ -0,0 +1,4 @@
|
||||
# generate pmf constants
|
||||
|
||||
Those constants are stored in PoorManFloatConst.h and are autogenerated
|
||||
by invoking make. This builds main from main.cpp.
|
||||
86
extras/gen_pmf_const/main.cpp
Normal file
86
extras/gen_pmf_const/main.cpp
Normal file
@@ -0,0 +1,86 @@
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
|
||||
#include <PoorManFloat.h>
|
||||
|
||||
void out(const char *name, float x, pmf_logarithmic value) {
|
||||
float ld2 = log2(x);
|
||||
float pmf = ld2 * 512;
|
||||
int16_t pmf_int = (uint16_t)round(pmf);
|
||||
puts("");
|
||||
printf("// %s = %f %d = 0x%04x\n", name, pmf, pmf_int, pmf_int);
|
||||
if (pmf_int != value) {
|
||||
printf("// %s should be 0x%04x\n", name, pmf_int);
|
||||
}
|
||||
printf("#define %s ((pmf_logarithmic)0x%04x)\n", name, value);
|
||||
float back = pow(2.0, float(pmf_int) / 512);
|
||||
printf("// => converted back => %.2f\n", back);
|
||||
}
|
||||
|
||||
int main() {
|
||||
puts("// Autogenerated by extras/gen_pmf_const/main");
|
||||
puts("// DO NOT EDIT");
|
||||
puts("#ifndef POORMANFLOATCONST_H");
|
||||
puts("#define POORMANFLOATCONST_H");
|
||||
puts("");
|
||||
puts("#include <PoorManFloat.h>");
|
||||
|
||||
pmf_logarithmic x;
|
||||
|
||||
x = pmfl_from((uint8_t)1);
|
||||
out("PMF_CONST_1", 1.0, x);
|
||||
|
||||
x = pmfl_shr(pmfl_from((uint8_t)3), 1);
|
||||
out("PMF_CONST_3_DIV_2", 1.5, x);
|
||||
|
||||
x = pmfl_multiply(pmfl_from((uint32_t)16e6), pmfl_from((uint32_t)8e6));
|
||||
out("PMF_CONST_128E12", 1.28e14, x);
|
||||
|
||||
x = pmfl_from((uint32_t)16e6);
|
||||
out("PMF_CONST_16E6", 1.6e7, x);
|
||||
|
||||
x = pmfl_from((uint16_t)500);
|
||||
out("PMF_CONST_500", 500, x);
|
||||
|
||||
x = pmfl_from((uint16_t)1000);
|
||||
out("PMF_CONST_1000", 1000, x);
|
||||
|
||||
x = pmfl_from((uint16_t)2000);
|
||||
out("PMF_CONST_2000", 2000, x);
|
||||
|
||||
x = pmfl_from((uint16_t)32000);
|
||||
out("PMF_CONST_32000", 32000, x);
|
||||
|
||||
x = pmfl_multiply(pmfl_from((uint32_t)16e6), pmfl_from((uint32_t)8e6));
|
||||
x = pmfl_sqrt(x);
|
||||
out("PMF_CONST_16E6_DIV_SQRT_OF_2", 1.6e7 / sqrt(2), x);
|
||||
|
||||
x = pmfl_from((uint32_t)21e6);
|
||||
out("PMF_CONST_21E6", 21e6, x);
|
||||
|
||||
x = pmfl_from((uint16_t)42000);
|
||||
out("PMF_CONST_42000", 42000, x);
|
||||
|
||||
x = pmfl_divide(pmfl_from((uint32_t)21e6), pmfl_sqrt(pmfl_from((uint8_t)2)));
|
||||
out("PMF_CONST_21E6_DIV_SQRT_OF_2", 21e6 / sqrt(2), x);
|
||||
|
||||
x = pmfl_square(pmfl_from((uint32_t)21e6));
|
||||
x = pmfl_shr(x, 1);
|
||||
out("PMF_CONST_2205E11", 2.205e14, x);
|
||||
|
||||
x = pmfl_from(__UINT32_MAX__);
|
||||
out("PMF_CONST_UINT32_MAX", __UINT32_MAX__, x);
|
||||
|
||||
x = pmfl_from((uint16_t)__UINT16_MAX__);
|
||||
out("PMF_CONST_UINT16_MAX", __UINT16_MAX__, x);
|
||||
|
||||
puts("");
|
||||
puts("// used in PoorManFloat.cpp as example");
|
||||
printf("// ");
|
||||
x = pmfl_from((uint16_t)15373);
|
||||
out("PMF_CONST_15373", 15373, x);
|
||||
|
||||
puts("#endif");
|
||||
|
||||
return 0;
|
||||
}
|
||||
78
extras/idf_examples/UsageExample/UsageExample.cpp
Normal file
78
extras/idf_examples/UsageExample/UsageExample.cpp
Normal file
@@ -0,0 +1,78 @@
|
||||
#include "FastAccelStepper.h"
|
||||
|
||||
#include <cinttypes>
|
||||
|
||||
// As in StepperDemo for Motor 1 on ESP32
|
||||
#define dirPinStepper 18
|
||||
#define enablePinStepper 26
|
||||
#define stepPinStepper 17
|
||||
|
||||
FastAccelStepperEngine engine = FastAccelStepperEngine();
|
||||
FastAccelStepper *stepper = NULL;
|
||||
|
||||
void setup() {
|
||||
printf("START\n");
|
||||
|
||||
engine.init(0);
|
||||
|
||||
printf("Engine initialized\n");
|
||||
|
||||
for (uint8_t i = 0; i < 10; i++) {
|
||||
printf("LOOP %d\n", i);
|
||||
vTaskDelay(pdMS_TO_TICKS(500));
|
||||
// esp_task_wdt_reset();
|
||||
}
|
||||
stepper = engine.stepperConnectToPin(stepPinStepper);
|
||||
|
||||
printf("Stepper connected\n");
|
||||
for (uint8_t i = 0; i < 10; i++) {
|
||||
printf("LOOP %d\n", i);
|
||||
vTaskDelay(pdMS_TO_TICKS(500));
|
||||
// esp_task_wdt_reset();
|
||||
}
|
||||
|
||||
if (stepper) {
|
||||
stepper->setDirectionPin(dirPinStepper);
|
||||
stepper->setEnablePin(enablePinStepper);
|
||||
stepper->setAutoEnable(true);
|
||||
|
||||
// If auto enable/disable need delays, just add (one or both):
|
||||
// stepper->setDelayToEnable(50);
|
||||
// stepper->setDelayToDisable(1000);
|
||||
|
||||
stepper->setSpeedInUs(1000); // the parameter is us/step !!!
|
||||
stepper->setAcceleration(100);
|
||||
|
||||
#ifdef SUPPORT_ESP32_PULSE_COUNTER
|
||||
stepper->attachToPulseCounter(7);
|
||||
#endif
|
||||
|
||||
printf("Stepper initialized\n");
|
||||
} else {
|
||||
printf("No stepper\n");
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" void app_main() {
|
||||
setup();
|
||||
int32_t target = 0;
|
||||
while (true) {
|
||||
while (stepper->isRunning()) {
|
||||
// esp_task_wdt_reset();
|
||||
printf("pos=%" PRId32, stepper->getCurrentPosition());
|
||||
#ifdef SUPPORT_ESP32_PULSE_COUNTER
|
||||
int16_t pcnt = stepper->readPulseCounter();
|
||||
printf(" pcnt=%d", pcnt);
|
||||
#endif
|
||||
printf("\n");
|
||||
vTaskDelay(pdMS_TO_TICKS(500));
|
||||
}
|
||||
printf("done\n");
|
||||
vTaskDelay(pdMS_TO_TICKS(500));
|
||||
printf("move\n");
|
||||
target = 1000 - target;
|
||||
stepper->moveTo(target);
|
||||
}
|
||||
// WARNING: if program reaches end of function app_main() the MCU will
|
||||
// restart.
|
||||
}
|
||||
39
extras/scripts/build-idf-platformio.sh
Executable file
39
extras/scripts/build-idf-platformio.sh
Executable file
@@ -0,0 +1,39 @@
|
||||
#!/bin/sh
|
||||
|
||||
TARGETS=${1:-espidf}
|
||||
echo "execute for ${TARGETS}"
|
||||
|
||||
if [ "$GITHUB_WORKSPACE" != "" ]
|
||||
then
|
||||
# Make sure we are inside the github workspace
|
||||
cd $GITHUB_WORKSPACE
|
||||
fi
|
||||
|
||||
# Whatever this script is started from, cd to the top level
|
||||
ROOT=`git rev-parse --show-toplevel`
|
||||
cd $ROOT
|
||||
|
||||
# install platformio, if needed
|
||||
which pio
|
||||
if [ $? -ne 0 ]
|
||||
then
|
||||
# Install PlatformIO CLI
|
||||
export PATH=$PATH:~/.platformio/penv/bin
|
||||
curl -fsSL https://raw.githubusercontent.com/platformio/platformio-core-installer/master/get-platformio.py -o get-platformio.py
|
||||
python3 get-platformio.py
|
||||
|
||||
# Use automated install from pio run
|
||||
# pio platform install "atmelavr"
|
||||
# pio platform install "atmelsam"
|
||||
# pio platform install "espressif32"
|
||||
fi
|
||||
|
||||
set -e
|
||||
for i in pio_espidf/*
|
||||
do
|
||||
for p in ${TARGETS}
|
||||
do
|
||||
echo $p: $i
|
||||
(cd $i;pio run -s -e $p)
|
||||
done
|
||||
done
|
||||
59
extras/scripts/build-pio-dirs.sh
Executable file
59
extras/scripts/build-pio-dirs.sh
Executable file
@@ -0,0 +1,59 @@
|
||||
#!/bin/sh
|
||||
|
||||
echo "build directories"
|
||||
|
||||
if [ "$GITHUB_WORKSPACE" != "" ]
|
||||
then
|
||||
# Make sure we are inside the github workspace
|
||||
cd $GITHUB_WORKSPACE
|
||||
fi
|
||||
|
||||
# Whatever this script is started from, cd to the top level
|
||||
ROOT=`git rev-parse --show-toplevel`
|
||||
cd $ROOT
|
||||
|
||||
pwd
|
||||
|
||||
# So create the pio_dirs-directory during the github action
|
||||
rm -fR pio_dirs
|
||||
mkdir pio_dirs
|
||||
for i in `ls examples`
|
||||
do
|
||||
mkdir -p pio_dirs/$i/src
|
||||
cd pio_dirs/$i
|
||||
ln -s ../../extras/ci/platformio.ini .
|
||||
cd src
|
||||
FILES=`cd ../../../examples/$i;find . -type f`
|
||||
for f in $FILES;do ln -s ../../../examples/$i/$f .;done
|
||||
cd ../../..
|
||||
done
|
||||
|
||||
# for espidf as of now, the src/* files need to be linked into the example build directory
|
||||
rm -fR pio_espidf
|
||||
mkdir pio_espidf
|
||||
for i in `cd extras;ls idf_examples`
|
||||
do
|
||||
mkdir -p pio_espidf/$i/src
|
||||
cd pio_espidf/$i
|
||||
ln -s ../../extras/ci/platformio.ini .
|
||||
cd src
|
||||
FILES=`cd ../../../extras/idf_examples/$i;find . -type f`
|
||||
for f in $FILES;do ln -s ../../../extras/idf_examples/$i/$f .;done
|
||||
cd ../../..
|
||||
done
|
||||
mkdir -p pio_espidf/StepperDemo/src
|
||||
(cd pio_espidf/StepperDemo;ln -s ../../extras/ci/platformio.ini;cd src;cp ../../../examples/StepperDemo/* .;mv StepperDemo.ino StepperDemo.cpp)
|
||||
|
||||
# Make one directory to test PoorManFloat on simulator
|
||||
mkdir pio_dirs/PMF_test
|
||||
mkdir pio_dirs/PMF_test/src
|
||||
cd pio_dirs/PMF_test
|
||||
ln -s ../../extras/ci/platformio.ini .
|
||||
cd src
|
||||
#sed -e 's/%d/%ld/g' <../../../tests/test_03.h >test_03.h
|
||||
ln -s ../../../extras/tests/pc_based/test_03.h .
|
||||
ln -s ../../../extras/tests/pc_based/PMF_test.ino PMF_test.ino
|
||||
cd ../../..
|
||||
|
||||
ls -al pio_*
|
||||
|
||||
43
extras/scripts/build-platformio.sh
Executable file
43
extras/scripts/build-platformio.sh
Executable file
@@ -0,0 +1,43 @@
|
||||
#!/bin/sh
|
||||
|
||||
TARGETS=${1:-nanoatmega168 nanoatmega328 atmega2560 esp32 esp32s2 esp32c3 atmelsam atmega32u4}
|
||||
echo "execute for ${TARGETS}"
|
||||
|
||||
if [ "$GITHUB_WORKSPACE" != "" ]
|
||||
then
|
||||
# Make sure we are inside the github workspace
|
||||
cd $GITHUB_WORKSPACE
|
||||
fi
|
||||
|
||||
# Whatever this script is started from, cd to the top level
|
||||
ROOT=`git rev-parse --show-toplevel`
|
||||
cd $ROOT
|
||||
|
||||
# install platformio, if needed
|
||||
which pio
|
||||
if [ $? -ne 0 ]
|
||||
then
|
||||
# Install PlatformIO CLI
|
||||
export PATH=$PATH:~/.platformio/penv/bin
|
||||
curl -fsSL https://raw.githubusercontent.com/platformio/platformio-core-installer/master/get-platformio.py -o get-platformio.py
|
||||
python3 get-platformio.py
|
||||
|
||||
# Use automated install from pio run
|
||||
# pio platform install "atmelavr"
|
||||
# pio platform install "atmelsam"
|
||||
# pio platform install "espressif32"
|
||||
fi
|
||||
|
||||
set -e
|
||||
for i in pio_dirs/*
|
||||
do
|
||||
for p in ${TARGETS}
|
||||
do
|
||||
if [ "$p" = "nanoatmega168" ] && [ "$i" = "pio_dirs/StepperDemo" ]; then
|
||||
echo $p: Skipping $i for $p due to space constraints
|
||||
continue
|
||||
fi
|
||||
echo $p: $i
|
||||
(cd $i;pio run -s -e $p)
|
||||
done
|
||||
done
|
||||
11
extras/scripts/format_code.sh
Executable file
11
extras/scripts/format_code.sh
Executable file
@@ -0,0 +1,11 @@
|
||||
#!/bin/sh
|
||||
|
||||
PRJ_ROOT=`git rev-parse --show-toplevel`
|
||||
VERSION=`git rev-parse --short HEAD`
|
||||
|
||||
FILES=`find ${PRJ_ROOT} -type f -name '*.ino' -or -type f -name '*.cpp' -or -type f -name '*.h'`
|
||||
|
||||
clang-format -style="{BasedOnStyle: Google, SortIncludes: false}" -i ${FILES}
|
||||
echo ${VERSION}
|
||||
sed -i -e 's/#define VERSION.*$$/#define VERSION "post-$(VERSION)"/' ${PRJ_ROOT}/examples/StepperDemo/StepperDemo.ino
|
||||
|
||||
50
extras/scripts/header2markdown.sh
Executable file
50
extras/scripts/header2markdown.sh
Executable file
@@ -0,0 +1,50 @@
|
||||
#!/bin/sh
|
||||
|
||||
# This extract all lines with C-comments // as plain text
|
||||
# Places all C-lines in quotes
|
||||
|
||||
gawk '
|
||||
BEGIN {
|
||||
in_c_header = 1
|
||||
in_code = 0
|
||||
quote_code = 0
|
||||
}
|
||||
|
||||
/#include/ { next }
|
||||
(NF != 0) && (in_c_header == 1) { next }
|
||||
/\/\/ *clang-format/ { next }
|
||||
|
||||
{ in_c_header = 0 }
|
||||
|
||||
(NF == 0) {
|
||||
if (in_code == 1) {
|
||||
print("```")
|
||||
}
|
||||
in_code = 0
|
||||
quote_code = 0
|
||||
next
|
||||
}
|
||||
|
||||
/\/\// {
|
||||
if (in_code == 1) {
|
||||
print("```")
|
||||
}
|
||||
|
||||
gsub("[ \t]*// ?","")
|
||||
print
|
||||
in_code = 0
|
||||
quote_code = 1
|
||||
next
|
||||
}
|
||||
|
||||
(quote_code == 1) {
|
||||
print("```cpp")
|
||||
in_code = 1
|
||||
quote_code = 0
|
||||
}
|
||||
|
||||
in_code == 1 {
|
||||
gsub("inline ","")
|
||||
print
|
||||
}
|
||||
' ../../src/FastAccelStepper.h >../doc/FastAccelStepper_API.md
|
||||
29
extras/tests/esp32_hw_based/Makefile
Normal file
29
extras/tests/esp32_hw_based/Makefile
Normal file
@@ -0,0 +1,29 @@
|
||||
all: compile test
|
||||
|
||||
DEV=ttyUSB0
|
||||
|
||||
test: M1.test M7.test
|
||||
|
||||
%.test:
|
||||
MOTOR=$* ./seq_04.sh $(DEV)
|
||||
MOTOR=$* ./seq_05.sh $(DEV)
|
||||
MOTOR=$* ./seq_06.sh $(DEV)
|
||||
MOTOR=$* ./seq_01a.sh $(DEV)
|
||||
MOTOR=$* ./seq_01b.sh $(DEV)
|
||||
MOTOR=$* ./seq_02.sh $(DEV)
|
||||
MOTOR=$* ./seq_07a.sh $(DEV)
|
||||
MOTOR=$* ./seq_07b.sh $(DEV)
|
||||
MOTOR=$* ./seq_07c.sh $(DEV)
|
||||
MOTOR=$* ./seq_03.sh $(DEV)
|
||||
|
||||
compile:
|
||||
(cd ../../../pio_dirs/StepperDemo;rm -fR .pio; pio run -e esp32_V6_8_1 -t upload --upload-port /dev/$(DEV))
|
||||
|
||||
compile_idf4:
|
||||
(cd ../../../pio_espidf/StepperDemo;rm -fR .pio; pio run -e esp32_idf_V5_3_0 -t upload --upload-port /dev/$(DEV))
|
||||
|
||||
compile_idf5:
|
||||
(cd ../../../pio_espidf/StepperDemo;rm -fR .pio; pio run -e esp32_idf_V6_8_1 -t upload --upload-port /dev/$(DEV))
|
||||
|
||||
clean:
|
||||
rm -f seq*.log
|
||||
51
extras/tests/esp32_hw_based/judge_pcnt_sync.awk
Normal file
51
extras/tests/esp32_hw_based/judge_pcnt_sync.awk
Normal file
@@ -0,0 +1,51 @@
|
||||
BEGIN {
|
||||
pass = 1
|
||||
}
|
||||
|
||||
# This is for running motor
|
||||
/^M[17]:/ {
|
||||
api = substr($2,2)
|
||||
pcnt = substr($3,2,length($3)-2)
|
||||
if (pcnt < 0) {
|
||||
if (api > 0) {
|
||||
while (pcnt < 0) {
|
||||
pcnt += 32767
|
||||
}
|
||||
}
|
||||
}
|
||||
api = api % 32767
|
||||
delta = pcnt - api
|
||||
if (api > pcnt) {
|
||||
delta = api - pcnt
|
||||
}
|
||||
if ((delta > 66) && (delta < 32767-66)) {
|
||||
print
|
||||
print api, pcnt
|
||||
pass = 0
|
||||
print "FAIL HERE ^^^"
|
||||
}
|
||||
}
|
||||
# This is for selected motor
|
||||
/^>> M[17]:/ {
|
||||
print
|
||||
api = substr($3,2)
|
||||
api = api % 32767
|
||||
pcnt = substr($4,2,length($4)-2)
|
||||
if (pcnt < 0) {
|
||||
pcnt += 32767
|
||||
}
|
||||
if (api != pcnt) {
|
||||
print api, pcnt
|
||||
pass = 0
|
||||
print "FAIL HERE ^^^"
|
||||
}
|
||||
}
|
||||
|
||||
END {
|
||||
if (pass) {
|
||||
print "PASS"
|
||||
}
|
||||
else {
|
||||
print "FAIL"
|
||||
}
|
||||
}
|
||||
34
extras/tests/esp32_hw_based/seq_01a.sh
Executable file
34
extras/tests/esp32_hw_based/seq_01a.sh
Executable file
@@ -0,0 +1,34 @@
|
||||
#!/bin/sh
|
||||
TTY=${1:-ttyUSB0}
|
||||
DEV="-d /dev/${TTY} -b 115200"
|
||||
MOTOR=${MOTOR:-M1}
|
||||
|
||||
CMD="$MOTOR p7,-32767,32767 H25000 A10000 f w1000 X w100 pc R100 w100 W R1000 w1000 W "
|
||||
PASS=">> $MOTOR: @1100 \\[1100\\]"
|
||||
|
||||
LOG="$0.log"
|
||||
|
||||
grabserial $DEV -c ' x reset ' -q "$MOTOR:" -e 10
|
||||
sleep 2
|
||||
|
||||
grabserial $DEV -c "$CMD" -q "$PASS" -e 10 -o $LOG
|
||||
echo
|
||||
|
||||
#if [ `gawk -f judge_pcnt_sync.awk $LOG | grep -c PASS` -ne 1 ]
|
||||
#then
|
||||
# grabserial $DEV -c 'r ' -q StepperDemo -e 1
|
||||
# echo
|
||||
# echo FAIL $0 pulse counter mismatch
|
||||
# exit 1
|
||||
#fi
|
||||
|
||||
if [ `grep -c "$PASS" $LOG` -eq 1 ]
|
||||
then
|
||||
echo PASS
|
||||
else
|
||||
grabserial $DEV -c ' r ' -q StepperDemo -e 1
|
||||
echo
|
||||
echo "FAIL $0 result pattern: $PASS"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
34
extras/tests/esp32_hw_based/seq_01b.sh
Executable file
34
extras/tests/esp32_hw_based/seq_01b.sh
Executable file
@@ -0,0 +1,34 @@
|
||||
#!/bin/sh
|
||||
TTY=${1:-ttyUSB0}
|
||||
DEV="-d /dev/${TTY} -b 115200"
|
||||
MOTOR=${MOTOR:-M1}
|
||||
|
||||
CMD="$MOTOR p7,-32767,32767 H25000 A10000 f w1000 X W pc R100 w100 W R1000 w1000 W "
|
||||
PASS=">> $MOTOR: @1100 \\[1100\\]"
|
||||
|
||||
LOG="$0.log"
|
||||
|
||||
grabserial $DEV -c ' x reset ' -q "$MOTOR:" -e 10
|
||||
sleep 2
|
||||
|
||||
grabserial $DEV -c "$CMD" -q "$PASS" -e 10 -o $LOG
|
||||
echo
|
||||
|
||||
#if [ `gawk -f judge_pcnt_sync.awk $LOG | grep -c PASS` -ne 1 ]
|
||||
#then
|
||||
# grabserial $DEV -c 'r ' -q StepperDemo -e 1
|
||||
# echo
|
||||
# echo FAIL $0 pulse counter mismatch
|
||||
# exit 1
|
||||
#fi
|
||||
|
||||
if [ `grep -c "$PASS" $LOG` -eq 1 ]
|
||||
then
|
||||
echo PASS
|
||||
else
|
||||
grabserial $DEV -c ' r ' -q StepperDemo -e 1
|
||||
echo
|
||||
echo "FAIL $0 result pattern: $PASS"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
34
extras/tests/esp32_hw_based/seq_01c.sh
Executable file
34
extras/tests/esp32_hw_based/seq_01c.sh
Executable file
@@ -0,0 +1,34 @@
|
||||
#!/bin/sh
|
||||
TTY=${1:-ttyUSB0}
|
||||
DEV="-d /dev/${TTY} -b 115200"
|
||||
MOTOR=${MOTOR:-M1}
|
||||
|
||||
CMD="$MOTOR p7,-32767,32767 H25000 A10000 f w10 X W pc w 20 R1 W "
|
||||
PASS=">> $MOTOR: @1 \\[1\\]"
|
||||
|
||||
LOG="$0.log"
|
||||
|
||||
grabserial $DEV -c ' x reset ' -q "$MOTOR:" -e 3
|
||||
sleep 2
|
||||
|
||||
grabserial $DEV -c "$CMD" -q "$PASS" -e 10 -o $LOG
|
||||
echo
|
||||
|
||||
#if [ `gawk -f judge_pcnt_sync.awk $LOG | grep -c PASS` -ne 1 ]
|
||||
#then
|
||||
# grabserial $DEV -c 'r ' -q StepperDemo -e 1
|
||||
# echo
|
||||
# echo FAIL $0 pulse counter mismatch
|
||||
# exit 1
|
||||
#fi
|
||||
|
||||
if [ `grep -c "$PASS" $LOG` -eq 1 ]
|
||||
then
|
||||
echo PASS
|
||||
else
|
||||
# grabserial $DEV -c ' r ' -q StepperDemo -e 1
|
||||
echo
|
||||
echo "FAIL $0 result pattern: $PASS"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
32
extras/tests/esp32_hw_based/seq_02.sh
Executable file
32
extras/tests/esp32_hw_based/seq_02.sh
Executable file
@@ -0,0 +1,32 @@
|
||||
#!/bin/sh
|
||||
TTY=${1:-ttyUSB0}
|
||||
DEV="-d /dev/${TTY} -b 115200"
|
||||
MOTOR=${MOTOR:-M1}
|
||||
|
||||
CMD="$MOTOR p7,-32767,32767 H30000 A100000 R30000 "
|
||||
PASS=">> $MOTOR: @30000 \\[30000\\]"
|
||||
|
||||
LOG="$0.log"
|
||||
|
||||
grabserial $DEV -c ' x reset ' -q "$MOTOR:" -e 10
|
||||
sleep 2
|
||||
|
||||
grabserial $DEV -c "$CMD" -q "$PASS" -e 3 -o $LOG
|
||||
echo
|
||||
|
||||
if [ `gawk -f judge_pcnt_sync.awk $LOG | grep -c PASS` -ne 1 ]
|
||||
then
|
||||
grabserial $DEV -c 'r ' -q StepperDemo -e 1
|
||||
echo
|
||||
echo FAIL $0 pulse counter mismatch
|
||||
exit 1
|
||||
fi
|
||||
if [ `grep -c "$PASS" $LOG` -eq 1 ]
|
||||
then
|
||||
echo PASS
|
||||
else
|
||||
grabserial $DEV -c ' r ' -q StepperDemo -e 1
|
||||
echo
|
||||
echo "FAIL $0 result pattern: $PASS"
|
||||
exit 1
|
||||
fi
|
||||
43
extras/tests/esp32_hw_based/seq_03.sh
Executable file
43
extras/tests/esp32_hw_based/seq_03.sh
Executable file
@@ -0,0 +1,43 @@
|
||||
#!/bin/sh
|
||||
TTY=${1:-ttyUSB0}
|
||||
DEV="-d /dev/${TTY} -b 115200"
|
||||
MOTOR=${MOTOR:-M1}
|
||||
|
||||
COMPLETE="test completed"
|
||||
PASS="test passed"
|
||||
MAX_RUN_S=300
|
||||
|
||||
# rmt has failed once 07, but repetitions are ok
|
||||
for SEQ in 13 01 02 03 04 06 07 10 11
|
||||
do
|
||||
LOG="$0_$SEQ.log"
|
||||
CMD="$MOTOR p7,-32767,32767 t $MOTOR $SEQ R "
|
||||
|
||||
echo "reset esp32"
|
||||
grabserial $DEV -c ' x reset ' -q "$MOTOR:" -e 10
|
||||
sleep 2
|
||||
|
||||
echo "send commands"
|
||||
grabserial $DEV -c "$CMD" -q "$COMPLETE" -e $MAX_RUN_S -o $LOG
|
||||
echo
|
||||
|
||||
if [ `gawk -f judge_pcnt_sync.awk $LOG | grep -c PASS` -ne 1 ]
|
||||
then
|
||||
grabserial $DEV -c 'r ' -q StepperDemo -e 1
|
||||
echo
|
||||
echo FAIL $0 pulse counter mismatch
|
||||
echo "test sequence $SEQ"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ `grep -c "$PASS" $LOG` -eq 1 ]
|
||||
then
|
||||
echo PASS
|
||||
else
|
||||
grabserial $DEV -c ' x r ' -q StepperDemo -e 1
|
||||
echo
|
||||
echo "FAIL $0 result pattern: $PASS"
|
||||
echo "test sequence $SEQ"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
34
extras/tests/esp32_hw_based/seq_04.sh
Executable file
34
extras/tests/esp32_hw_based/seq_04.sh
Executable file
@@ -0,0 +1,34 @@
|
||||
#!/bin/sh
|
||||
TTY=${1:-ttyUSB0}
|
||||
DEV="-d /dev/${TTY} -b 115200"
|
||||
MOTOR=${MOTOR:-M1}
|
||||
|
||||
CMD="$MOTOR p7,-32767,32767 H25000 A10000 R1 W "
|
||||
PASS=">> $MOTOR: @1 \\[1\\]"
|
||||
|
||||
LOG="$0.log"
|
||||
|
||||
grabserial $DEV -c ' x reset ' -q "$MOTOR:" -e 10
|
||||
sleep 2
|
||||
|
||||
grabserial $DEV -c "$CMD" -q "$PASS" -e 3 -o $LOG
|
||||
echo
|
||||
|
||||
#if [ `gawk -f judge_pcnt_sync.awk $LOG | grep -c PASS` -ne 1 ]
|
||||
#then
|
||||
# grabserial $DEV -c 'r ' -q StepperDemo -e 1
|
||||
# echo
|
||||
# echo FAIL $0 pulse counter mismatch
|
||||
# exit 1
|
||||
#fi
|
||||
|
||||
if [ `grep -c "$PASS" $LOG` -eq 1 ]
|
||||
then
|
||||
echo PASS
|
||||
else
|
||||
grabserial $DEV -c ' r ' -q StepperDemo -e 1
|
||||
echo
|
||||
echo "FAIL $0 result pattern: $PASS"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
34
extras/tests/esp32_hw_based/seq_05.sh
Executable file
34
extras/tests/esp32_hw_based/seq_05.sh
Executable file
@@ -0,0 +1,34 @@
|
||||
#!/bin/sh
|
||||
TTY=${1:-ttyUSB0}
|
||||
DEV="-d /dev/${TTY} -b 115200"
|
||||
MOTOR=${MOTOR:-M1}
|
||||
|
||||
CMD="$MOTOR H25000 A10000 R1000 w200 X W p7,-32767,32767 ? R10 w1000 "
|
||||
PASS=">> $MOTOR: @10 \\[10\\]"
|
||||
|
||||
LOG="$0.log"
|
||||
|
||||
grabserial $DEV -c ' x reset ' -q "$MOTOR:" -e 10
|
||||
sleep 2
|
||||
|
||||
grabserial $DEV -c "$CMD" -q "$PASS" -e 3 -o $LOG
|
||||
echo
|
||||
|
||||
#if [ `gawk -f judge_pcnt_sync.awk $LOG | grep -c PASS` -ne 1 ]
|
||||
#then
|
||||
# grabserial $DEV -c 'r ' -q StepperDemo -e 1
|
||||
# echo
|
||||
# echo FAIL $0 pulse counter mismatch
|
||||
# exit 1
|
||||
#fi
|
||||
|
||||
if [ `grep -c "$PASS" $LOG` -eq 1 ]
|
||||
then
|
||||
echo PASS
|
||||
else
|
||||
grabserial $DEV -c ' r ' -q StepperDemo -e 1
|
||||
echo
|
||||
echo "FAIL $0 result pattern: $PASS"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
34
extras/tests/esp32_hw_based/seq_06.sh
Executable file
34
extras/tests/esp32_hw_based/seq_06.sh
Executable file
@@ -0,0 +1,34 @@
|
||||
#!/bin/sh
|
||||
TTY=${1:-ttyUSB0}
|
||||
DEV="-d /dev/${TTY} -b 115200"
|
||||
MOTOR=${MOTOR:-M1}
|
||||
|
||||
CMD="$MOTOR p7,-32767,32767 V40 A1000000 R54 W "
|
||||
PASS=">> $MOTOR: @54 \\[54\\]"
|
||||
|
||||
LOG="$0.log"
|
||||
|
||||
grabserial $DEV -c ' x reset ' -q "$MOTOR:" -e 10
|
||||
sleep 2
|
||||
|
||||
grabserial $DEV -c "$CMD" -q "$PASS" -e 3 -o $LOG
|
||||
echo
|
||||
|
||||
#if [ `gawk -f judge_pcnt_sync.awk $LOG | grep -c PASS` -ne 1 ]
|
||||
#then
|
||||
# grabserial $DEV -c 'r ' -q StepperDemo -e 1
|
||||
# echo
|
||||
# echo FAIL $0 pulse counter mismatch
|
||||
# exit 1
|
||||
#fi
|
||||
|
||||
if [ `grep -c "$PASS" $LOG` -eq 1 ]
|
||||
then
|
||||
echo PASS
|
||||
else
|
||||
grabserial $DEV -c ' r ' -q StepperDemo -e 1
|
||||
echo
|
||||
echo "FAIL $0 result pattern: $PASS"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
34
extras/tests/esp32_hw_based/seq_07a.sh
Executable file
34
extras/tests/esp32_hw_based/seq_07a.sh
Executable file
@@ -0,0 +1,34 @@
|
||||
#!/bin/sh
|
||||
TTY=${1:-ttyUSB0}
|
||||
DEV="-d /dev/${TTY} -b 115200"
|
||||
MOTOR=${MOTOR:-M1}
|
||||
|
||||
CMD="$MOTOR p7,-32767,32767 V40 A1000 R54 W R-54 W"
|
||||
PASS=">> $MOTOR: @0 \\[0\\]"
|
||||
|
||||
LOG="$0.log"
|
||||
|
||||
grabserial $DEV -c ' x reset ' -q "$MOTOR:" -e 10
|
||||
sleep 2
|
||||
|
||||
grabserial $DEV -c "$CMD" -q "$PASS" -e 3 -o $LOG
|
||||
echo
|
||||
|
||||
#if [ `gawk -f judge_pcnt_sync.awk $LOG | grep -c PASS` -ne 1 ]
|
||||
#then
|
||||
# grabserial $DEV -c 'r ' -q StepperDemo -e 1
|
||||
# echo
|
||||
# echo FAIL $0 pulse counter mismatch
|
||||
# exit 1
|
||||
#fi
|
||||
|
||||
if [ `grep -c "$PASS" $LOG` -eq 1 ]
|
||||
then
|
||||
echo PASS
|
||||
else
|
||||
grabserial $DEV -c ' r ' -q StepperDemo -e 1
|
||||
echo
|
||||
echo "FAIL $0 result pattern: $PASS"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
34
extras/tests/esp32_hw_based/seq_07b.sh
Executable file
34
extras/tests/esp32_hw_based/seq_07b.sh
Executable file
@@ -0,0 +1,34 @@
|
||||
#!/bin/sh
|
||||
TTY=${1:-ttyUSB0}
|
||||
DEV="-d /dev/${TTY} -b 115200"
|
||||
MOTOR=${MOTOR:-M1}
|
||||
|
||||
CMD="$MOTOR p7,-32767,32767 V40 A1000 R20 W R-19 W"
|
||||
PASS=">> $MOTOR: @1 \\[1\\]"
|
||||
|
||||
LOG="$0.log"
|
||||
|
||||
grabserial $DEV -c ' x reset ' -q "$MOTOR:" -e 10
|
||||
sleep 2
|
||||
|
||||
grabserial $DEV -c "$CMD" -q "$PASS" -e 3 -o $LOG
|
||||
echo
|
||||
|
||||
#if [ `gawk -f judge_pcnt_sync.awk $LOG | grep -c PASS` -ne 1 ]
|
||||
#then
|
||||
# grabserial $DEV -c 'r ' -q StepperDemo -e 1
|
||||
# echo
|
||||
# echo FAIL $0 pulse counter mismatch
|
||||
# exit 1
|
||||
#fi
|
||||
|
||||
if [ `grep -c "$PASS" $LOG` -eq 1 ]
|
||||
then
|
||||
echo PASS
|
||||
else
|
||||
grabserial $DEV -c ' r ' -q StepperDemo -e 1
|
||||
echo
|
||||
echo "FAIL $0 result pattern: $PASS"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
34
extras/tests/esp32_hw_based/seq_07c.sh
Executable file
34
extras/tests/esp32_hw_based/seq_07c.sh
Executable file
@@ -0,0 +1,34 @@
|
||||
#!/bin/sh
|
||||
TTY=${1:-ttyUSB0}
|
||||
DEV="-d /dev/${TTY} -b 115200"
|
||||
MOTOR=${MOTOR:-M1}
|
||||
|
||||
CMD="$MOTOR p7,-32767,32767 V40 A1000 R20 W "
|
||||
PASS=">> $MOTOR: @20 \\[20\\]"
|
||||
|
||||
LOG="$0.log"
|
||||
|
||||
grabserial $DEV -c ' x reset ' -q "$MOTOR:" -e 10
|
||||
sleep 2
|
||||
|
||||
grabserial $DEV -c "$CMD" -q "$PASS" -e 3 -o $LOG
|
||||
echo
|
||||
|
||||
#if [ `gawk -f judge_pcnt_sync.awk $LOG | grep -c PASS` -ne 1 ]
|
||||
#then
|
||||
# grabserial $DEV -c 'r ' -q StepperDemo -e 1
|
||||
# echo
|
||||
# echo FAIL $0 pulse counter mismatch
|
||||
# exit 1
|
||||
#fi
|
||||
|
||||
if [ `grep -c "$PASS" $LOG` -eq 1 ]
|
||||
then
|
||||
echo PASS
|
||||
else
|
||||
grabserial $DEV -c ' r ' -q StepperDemo -e 1
|
||||
echo
|
||||
echo "FAIL $0 result pattern: $PASS"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
33
extras/tests/esp32_hw_based/seq_xxx.sh.off
Executable file
33
extras/tests/esp32_hw_based/seq_xxx.sh.off
Executable file
@@ -0,0 +1,33 @@
|
||||
#!/bin/sh
|
||||
DEV="-d /dev/ttyUSB0 -b 115200"
|
||||
|
||||
CMD="M1 p7,0,0 t M1 07 R "
|
||||
PASS="Test passed"
|
||||
MAX_RUN_S=10
|
||||
|
||||
LOG="$0.log"
|
||||
|
||||
grabserial $DEV -c 'reset ' -q "M1:" -e 10
|
||||
sleep 2
|
||||
|
||||
grabserial $DEV -c "$CMD" -q "$PASS" -e $MAX_RUN_S -o $LOG
|
||||
echo
|
||||
|
||||
if [ `gawk -f judge_pcnt_sync.awk $LOG | grep -c PASS` -ne 1 ]
|
||||
then
|
||||
grabserial $DEV -c 'r ' -q StepperDemo -e 1
|
||||
echo
|
||||
echo FAIL $0 pulse counter mismatch
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ `grep -c "$PASS" $LOG` -eq 1 ]
|
||||
then
|
||||
echo PASS
|
||||
else
|
||||
grabserial $DEV -c 'r ' -q StepperDemo -e 1
|
||||
echo
|
||||
echo "FAIL $0 result pattern: $PASS"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
13
extras/tests/esp32_hw_based/test_all.sh
Normal file
13
extras/tests/esp32_hw_based/test_all.sh
Normal file
@@ -0,0 +1,13 @@
|
||||
#!/bin/sh
|
||||
|
||||
# arduino idf4 based test
|
||||
make compile
|
||||
make M1.test M7.test
|
||||
|
||||
# idf4 based test
|
||||
make compile_idf4
|
||||
make M1.test M7.test
|
||||
|
||||
# idf5 only rmt-module supporting 8 steppers
|
||||
make compile_idf5
|
||||
make M1.test
|
||||
58
extras/tests/pc_based/Makefile
Normal file
58
extras/tests/pc_based/Makefile
Normal file
@@ -0,0 +1,58 @@
|
||||
|
||||
PRJ_ROOT=$(shell git rev-parse --show-toplevel)
|
||||
CFLAGS=-DTEST -Werror -g -I$(PRJ_ROOT)/src
|
||||
CXXFLAGS=-DTEST -Werror -g -DF_CPU=16000000 -I$(PRJ_ROOT)/src
|
||||
LDLIBS=-lm -lc
|
||||
|
||||
TESTS=$(basename $(wildcard test_??.cpp))
|
||||
|
||||
test: $(TESTS) pmf_test rmc_test
|
||||
./rmc_test
|
||||
./pmf_test
|
||||
rm -f test.log
|
||||
$(addsuffix >>test.log &&,$(addprefix ./,$(TESTS))) echo "All tests passed"
|
||||
|
||||
LIB_H=FastAccelStepper.h PoorManFloat.h StepperISR.h \
|
||||
RampGenerator.h RampConstAcceleration.h RampCalculator.h \
|
||||
fas_arch/common.h
|
||||
LIB_O=FastAccelStepper.o PoorManFloat.o StepperISR_test.o \
|
||||
RampGenerator.o RampConstAcceleration.o RampCalculator.o StepperISR.o
|
||||
|
||||
SRC_LIB_H=$(addprefix $(PRJ_ROOT)/src/,$(LIB_H))
|
||||
|
||||
test_%: test_%.o $(LIB_O)
|
||||
gcc -o $@ $< $(LIB_O) $(LDLIBS)
|
||||
|
||||
test_%.o: test_%.cpp $(SRC_LIB_H) RampChecker.h stubs.h
|
||||
g++ -c $(CXXFLAGS) -o $@ $<
|
||||
|
||||
pmf_test: pmf_test.o PoorManFloat.o
|
||||
pmf_test.o: pmf_test.cpp $(PRJ_ROOT)/src/PoorManFloat.h stubs.h test_03.h
|
||||
|
||||
rmc_test: rmc_test.o PoorManFloat.o RampCalculator.o
|
||||
rmc_test.o: rmc_test.cpp $(PRJ_ROOT)/src/PoorManFloat.h $(PRJ_ROOT)/src/RampCalculator.h stubs.h test_03.h
|
||||
|
||||
FastAccelStepper.o: $(PRJ_ROOT)/src/FastAccelStepper.cpp $(SRC_LIB_H)
|
||||
$(COMPILE.cpp) $< -o $@
|
||||
|
||||
PoorManFloat.o: $(PRJ_ROOT)/src/PoorManFloat.cpp $(PRJ_ROOT)/src/PoorManFloat.h
|
||||
$(COMPILE.cpp) $< -o $@
|
||||
|
||||
RampGenerator.o: $(PRJ_ROOT)/src/RampGenerator.cpp $(SRC_LIB_H)
|
||||
$(COMPILE.cpp) $< -o $@
|
||||
|
||||
RampConstAcceleration.o: $(PRJ_ROOT)/src/RampConstAcceleration.cpp $(SRC_LIB_H)
|
||||
$(COMPILE.cpp) $< -o $@
|
||||
|
||||
RampCalculator.o: $(PRJ_ROOT)/src/RampCalculator.cpp $(SRC_LIB_H)
|
||||
$(COMPILE.cpp) $< -o $@
|
||||
|
||||
StepperISR.o: $(PRJ_ROOT)/src/StepperISR.cpp $(SRC_LIB_H)
|
||||
$(COMPILE.cpp) $< -o $@
|
||||
|
||||
StepperISR_test.o: StepperISR_test.cpp $(SRC_LIB_H)
|
||||
|
||||
VERSION=$(shell git rev-parse --short HEAD)
|
||||
|
||||
clean:
|
||||
rm -f *.o test_[0-9][0-9] *.gnuplot pmf_test rmc_test test.log
|
||||
59
extras/tests/pc_based/PMF_test.ino
Normal file
59
extras/tests/pc_based/PMF_test.ino
Normal file
@@ -0,0 +1,59 @@
|
||||
#include <stdint.h>
|
||||
|
||||
#include "PoorManFloat.h"
|
||||
|
||||
//
|
||||
// This file can be renamed to a .ino and compiled as sketch to be run on the
|
||||
// target e.g. arduino nano.
|
||||
//
|
||||
|
||||
#include <Arduino.h>
|
||||
#ifdef SIMULATOR
|
||||
#include <avr/sleep.h>
|
||||
#endif
|
||||
|
||||
uint16_t error_cnt = 0;
|
||||
char buffer[256];
|
||||
#define trace(s) Serial.println(s)
|
||||
#define xprintf(args...)
|
||||
#define test(x, msg) \
|
||||
if (!(x)) { \
|
||||
error_cnt++; \
|
||||
Serial.print("ERROR: "); \
|
||||
Serial.println(__LINE__); \
|
||||
};
|
||||
|
||||
#include "test_03.h"
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
Serial.println("Start test...");
|
||||
bool result = perform_test();
|
||||
if (result) {
|
||||
Serial.println("TEST PASSED");
|
||||
} else {
|
||||
Serial.print("TEST FAILED: ");
|
||||
Serial.print(error_cnt);
|
||||
Serial.println(" errors");
|
||||
}
|
||||
#ifdef SIMULATOR
|
||||
// if result is Ok. Toggle port twice, otherwise once
|
||||
#define PIN 10
|
||||
#define DIRPIN 7
|
||||
pinMode(DIRPIN, OUTPUT);
|
||||
digitalWrite(DIRPIN, HIGH);
|
||||
pinMode(PIN, OUTPUT);
|
||||
digitalWrite(PIN, HIGH);
|
||||
digitalWrite(PIN, LOW);
|
||||
if (result) {
|
||||
digitalWrite(PIN, HIGH);
|
||||
digitalWrite(PIN, LOW);
|
||||
}
|
||||
|
||||
delay(1000);
|
||||
noInterrupts();
|
||||
sleep_cpu();
|
||||
#endif
|
||||
}
|
||||
|
||||
void loop() {}
|
||||
46
extras/tests/pc_based/README.txt
Normal file
46
extras/tests/pc_based/README.txt
Normal file
@@ -0,0 +1,46 @@
|
||||
Tests;
|
||||
|
||||
- test_01
|
||||
check queue functionality
|
||||
|
||||
- test_02
|
||||
checks ramp timing
|
||||
|
||||
- pmf_test
|
||||
checks PoorManFloat implementation
|
||||
|
||||
- test_04
|
||||
one test case with speed change during ramp
|
||||
|
||||
- test_05
|
||||
check for move/moveTo while ramp is processing
|
||||
Introduce concept of interrupt generation during noInterrupts call
|
||||
|
||||
- test_06
|
||||
check for stop during move
|
||||
|
||||
- test_07
|
||||
test case with varying speed
|
||||
|
||||
- test_08
|
||||
ramp to max speed with step wise increased length
|
||||
|
||||
- test_09
|
||||
simple test case for V30 A1000000 R53 W R53
|
||||
|
||||
- test_10
|
||||
test case for V30 a17164 w2000 a-1000
|
||||
|
||||
- test 11
|
||||
test case for M1 A1000 V10000 f w300 V100000 U
|
||||
This is stuck in state RED.
|
||||
Revised test: M1 A1000 V10000 P100 w300 V100000 U
|
||||
|
||||
- test 12
|
||||
ramp up with 1 step/s^2 to 1000us/step
|
||||
|
||||
- test 13
|
||||
tests with maximum high acceleration
|
||||
|
||||
- test 14
|
||||
test case for issue #178: Speed jump instead of decrease
|
||||
142
extras/tests/pc_based/RampChecker.h
Normal file
142
extras/tests/pc_based/RampChecker.h
Normal file
@@ -0,0 +1,142 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
class RampChecker {
|
||||
public:
|
||||
uint64_t total_ticks;
|
||||
uint32_t last_dt;
|
||||
uint32_t min_dt;
|
||||
bool increase_ok;
|
||||
bool flat_ok;
|
||||
bool decrease_ok;
|
||||
bool first;
|
||||
bool dir_high;
|
||||
bool reversing_allowed;
|
||||
uint32_t accelerate_till;
|
||||
uint32_t coast_till;
|
||||
uint32_t time_coasting;
|
||||
uint32_t pos;
|
||||
uint32_t ticks_since_last_step;
|
||||
float avg_accel;
|
||||
FILE *gp_file;
|
||||
char filename[100];
|
||||
|
||||
void next_ramp() {
|
||||
increase_ok = true;
|
||||
decrease_ok = false;
|
||||
last_dt = ~0;
|
||||
min_dt = ~0;
|
||||
first = true;
|
||||
dir_high = true;
|
||||
coast_till = 0;
|
||||
time_coasting = 0;
|
||||
accelerate_till = 0;
|
||||
reversing_allowed = false;
|
||||
}
|
||||
RampChecker() {
|
||||
ticks_since_last_step = 0;
|
||||
avg_accel = 0;
|
||||
gp_file = NULL;
|
||||
total_ticks = 0;
|
||||
pos = 0;
|
||||
next_ramp();
|
||||
}
|
||||
void start_plot(char *fname) {
|
||||
int n = strlen(fname) - 8; // remove .gnuplot
|
||||
strncpy(filename, fname, n);
|
||||
filename[n] = 0;
|
||||
gp_file = fopen(fname, "w");
|
||||
fprintf(gp_file, "$data <<EOF\n");
|
||||
}
|
||||
void finish_plot() {
|
||||
if (gp_file != NULL) {
|
||||
fprintf(gp_file, "EOF\n");
|
||||
fprintf(gp_file, "set term pngcairo size 1600, 800\n");
|
||||
fprintf(gp_file, "set output \"%s.png\"\n", filename);
|
||||
fprintf(gp_file, "set multiplot layout 2,2\n");
|
||||
fprintf(gp_file, "set title \"speed [steps/s] over time [s]\"\n");
|
||||
fprintf(gp_file, "plot $data using 1:2 with lines notitle\n");
|
||||
fprintf(gp_file, "set title \"speed [steps/s] over position\"\n");
|
||||
fprintf(gp_file, "plot $data using 4:2 with lines notitle\n");
|
||||
fprintf(gp_file, "set title \"position over time [s]\"\n");
|
||||
fprintf(gp_file, "plot $data using 1:4 with lines notitle\n");
|
||||
fprintf(gp_file,
|
||||
"set title \"averaged (!) acceleration [steps/s*s] over time "
|
||||
"[s]\"\n");
|
||||
fprintf(gp_file, "plot $data using 1:5 with lines notitle\n");
|
||||
//fprintf(gp_file, "pause -1\n");
|
||||
fclose(gp_file);
|
||||
gp_file = NULL;
|
||||
}
|
||||
}
|
||||
void check_section(struct queue_entry *e) {
|
||||
uint8_t steps = e->steps;
|
||||
if (steps == 0) {
|
||||
// Just a pause
|
||||
if (ticks_since_last_step <= 0xffff0000) {
|
||||
ticks_since_last_step += e->ticks;
|
||||
}
|
||||
total_ticks += e->ticks;
|
||||
printf("process pause %d => %u\n", e->ticks, ticks_since_last_step);
|
||||
return;
|
||||
}
|
||||
if (e->toggle_dir) {
|
||||
assert(reversing_allowed);
|
||||
dir_high = !dir_high;
|
||||
increase_ok = true;
|
||||
last_dt = ~0;
|
||||
decrease_ok = false;
|
||||
}
|
||||
if (dir_high) {
|
||||
pos += steps;
|
||||
} else {
|
||||
pos -= steps;
|
||||
}
|
||||
uint32_t curr_dt = ticks_since_last_step;
|
||||
total_ticks += steps * e->ticks;
|
||||
if (!first) {
|
||||
min_dt = min(min_dt, curr_dt);
|
||||
}
|
||||
float accel = 0;
|
||||
if (last_dt != ~0) {
|
||||
accel = (16000000.0 / float(curr_dt) - 16000000.0 / float(last_dt)) /
|
||||
(1.0 / 16000000.0 * float(steps * curr_dt));
|
||||
avg_accel += (accel - avg_accel) / (steps * 20);
|
||||
}
|
||||
printf(
|
||||
"process command in ramp checker @%.6fs: steps = %d last = %u current "
|
||||
"= %u "
|
||||
" min_dt "
|
||||
"= %u accel=%.6f inc=%s dec=%s\n",
|
||||
total_ticks / 16000000.0, steps, last_dt, curr_dt, min_dt, accel,
|
||||
increase_ok ? "ALLOW" : "NO", decrease_ok ? "ALLOW" : "NO");
|
||||
|
||||
if (gp_file != NULL) {
|
||||
fprintf(gp_file, "%.6f %.2f %d %d %f\n", total_ticks / 16000000.0,
|
||||
16000000.0 / last_dt, last_dt, pos, avg_accel);
|
||||
}
|
||||
|
||||
assert(first || (steps * curr_dt > 0));
|
||||
|
||||
if (last_dt > curr_dt) {
|
||||
assert(increase_ok);
|
||||
accelerate_till = total_ticks;
|
||||
decrease_ok = true;
|
||||
} else if (last_dt < curr_dt) {
|
||||
if (increase_ok) {
|
||||
coast_till = total_ticks - curr_dt;
|
||||
}
|
||||
assert(decrease_ok);
|
||||
increase_ok = false;
|
||||
} else {
|
||||
time_coasting += steps * curr_dt;
|
||||
}
|
||||
|
||||
if (!first) {
|
||||
last_dt = curr_dt;
|
||||
}
|
||||
|
||||
ticks_since_last_step = e->ticks;
|
||||
first = false;
|
||||
}
|
||||
};
|
||||
124
extras/tests/pc_based/off_test_15.cpp
Normal file
124
extras/tests/pc_based/off_test_15.cpp
Normal file
@@ -0,0 +1,124 @@
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "FastAccelStepper.h"
|
||||
#include "StepperISR.h"
|
||||
|
||||
char TCCR1A;
|
||||
char TCCR1B;
|
||||
char TCCR1C;
|
||||
char TIMSK1;
|
||||
char TIFR1;
|
||||
unsigned short OCR1A;
|
||||
unsigned short OCR1B;
|
||||
|
||||
StepperQueue fas_queue[NUM_QUEUES];
|
||||
|
||||
void inject_fill_interrupt(int mark) {}
|
||||
void noInterrupts() {}
|
||||
void interrupts() {}
|
||||
|
||||
#include "RampChecker.h"
|
||||
|
||||
class FastAccelStepperTest {
|
||||
public:
|
||||
void init_queue() {
|
||||
fas_queue[0].read_idx = 0;
|
||||
fas_queue[1].read_idx = 0;
|
||||
fas_queue[0].next_write_idx = 0;
|
||||
fas_queue[1].next_write_idx = 0;
|
||||
}
|
||||
|
||||
void ramp() {
|
||||
init_queue();
|
||||
FastAccelStepper s = FastAccelStepper();
|
||||
s.init(NULL, 0, 0);
|
||||
RampChecker rc = RampChecker();
|
||||
assert(0 == s.getCurrentPosition());
|
||||
|
||||
assert(s.isQueueEmpty());
|
||||
s.setSpeedInHz(36800);
|
||||
s.setAcceleration(1000000);
|
||||
s.fill_queue();
|
||||
assert(s.isQueueEmpty());
|
||||
float old_planned_time_in_buffer = 0;
|
||||
|
||||
char fname[100];
|
||||
sprintf(fname, "test_15.gnuplot");
|
||||
rc.start_plot(fname);
|
||||
s.runForward();
|
||||
int32_t wait_ticks = TICKS_PER_S / 10;
|
||||
uint8_t state = 0;
|
||||
for (int i = 0; i < 2000; i++) {
|
||||
if ((state == 0) && (wait_ticks < rc.total_ticks)) {
|
||||
printf("New move\n");
|
||||
s.move(-100000);
|
||||
wait_ticks += TICKS_PER_S / 10;
|
||||
state += 1;
|
||||
}
|
||||
if ((state == 1) && (wait_ticks < rc.total_ticks)) {
|
||||
printf("move with changed acceleration\n");
|
||||
s.setAcceleration(5000);
|
||||
s.move(100000);
|
||||
wait_ticks += TICKS_PER_S / 10;
|
||||
state += 1;
|
||||
}
|
||||
if ((state == 2) && (wait_ticks < rc.total_ticks)) {
|
||||
printf("stop");
|
||||
s.stopMove();
|
||||
wait_ticks += 2 * TICKS_PER_S / 10;
|
||||
state += 1;
|
||||
}
|
||||
if (true) {
|
||||
printf(
|
||||
"Loop %d: Queue read/write = %d/%d Target pos = %d, Queue End "
|
||||
"pos = %d QueueEmpty=%s\n",
|
||||
i, fas_queue[0].read_idx, fas_queue[0].next_write_idx,
|
||||
s.targetPos(), s.getPositionAfterCommandsCompleted(),
|
||||
s.isQueueEmpty() ? "yes" : "no");
|
||||
}
|
||||
if (!s.isRampGeneratorActive()) {
|
||||
break;
|
||||
}
|
||||
s.fill_queue();
|
||||
if ((state == 3) && (wait_ticks < rc.total_ticks)) {
|
||||
break;
|
||||
}
|
||||
uint32_t from_dt = rc.total_ticks;
|
||||
while (!s.isQueueEmpty()) {
|
||||
rc.increase_ok = true;
|
||||
rc.decrease_ok = true;
|
||||
rc.check_section(
|
||||
&fas_queue[0].entry[fas_queue[0].read_idx & QUEUE_LEN_MASK]);
|
||||
fas_queue[0].read_idx++;
|
||||
}
|
||||
uint32_t to_dt = rc.total_ticks;
|
||||
float planned_time = (to_dt - from_dt) * 1.0 / 16000000;
|
||||
printf("planned time in buffer: %.6fs\n", planned_time);
|
||||
// This must be ensured, so that the stepper does not run out of
|
||||
// commands
|
||||
assert((i == 0) || (old_planned_time_in_buffer > 0.005));
|
||||
old_planned_time_in_buffer = planned_time;
|
||||
// stop after
|
||||
if (rc.total_ticks > TICKS_PER_S * 40) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
rc.finish_plot();
|
||||
// test(!s.isRampGeneratorActive(), "too many commands created");
|
||||
test(s.getCurrentPosition() > 70000, "stepper runs too slow");
|
||||
test(s.getCurrentPosition() < 80000, "stepper runs too fast");
|
||||
printf("Total time %f\n", rc.total_ticks / 16000000.0);
|
||||
|
||||
#if (TEST_CREATE_QUEUE_CHECKSUM == 1)
|
||||
printf("CHECKSUM for %d/%d/%d: %d\n", steps, travel_dt, accel, s.checksum);
|
||||
#endif
|
||||
}
|
||||
};
|
||||
int main() {
|
||||
FastAccelStepperTest test;
|
||||
test.ramp();
|
||||
printf("TEST_15 PASSED\n");
|
||||
return 0;
|
||||
}
|
||||
29
extras/tests/pc_based/pmf_test.cpp
Normal file
29
extras/tests/pc_based/pmf_test.cpp
Normal file
@@ -0,0 +1,29 @@
|
||||
#include <stdint.h>
|
||||
|
||||
#include "PoorManFloat.h"
|
||||
|
||||
//
|
||||
// This file can be renamed to a .ino and compiled as sketch to be run on the
|
||||
// target e.g. arduino nano.
|
||||
//
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#define trace puts
|
||||
#define xprintf printf
|
||||
#define test(x, msg) \
|
||||
if (!(x)) { \
|
||||
puts(msg); \
|
||||
assert(false); \
|
||||
};
|
||||
|
||||
unsigned int error_cnt = 0;
|
||||
|
||||
#include "test_03.h"
|
||||
|
||||
int main() {
|
||||
if (perform_test()) {
|
||||
xprintf("TEST_03 PASSED\n");
|
||||
}
|
||||
}
|
||||
94
extras/tests/pc_based/rmc_test.cpp
Normal file
94
extras/tests/pc_based/rmc_test.cpp
Normal file
@@ -0,0 +1,94 @@
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "RampCalculator.h"
|
||||
|
||||
// Not a real test case
|
||||
|
||||
int main() {
|
||||
uint32_t res;
|
||||
|
||||
// Calculation is pre_calc/sqrt(steps)
|
||||
//
|
||||
float ramp_acceleration = 10000.0;
|
||||
uint32_t max_speed_in_ticks = 1600;
|
||||
|
||||
struct ramp_config_s c;
|
||||
c.init();
|
||||
c.parameters.setAcceleration(ramp_acceleration);
|
||||
c.parameters.setSpeedInTicks(max_speed_in_ticks);
|
||||
|
||||
char fname[100];
|
||||
snprintf(fname, 100, "ramp.gnuplot");
|
||||
FILE *gp_file = fopen(fname, "w");
|
||||
fprintf(gp_file, "$data <<EOF\n");
|
||||
|
||||
uint64_t sum_ticks = 0;
|
||||
float old_speed = 0;
|
||||
for (uint32_t s = 1; s <= c.max_ramp_up_steps; s++) {
|
||||
uint32_t ticks = c.calculate_ticks(s);
|
||||
sum_ticks += ticks;
|
||||
float ideal_speed = float(sum_ticks) / 16000000.0 * ramp_acceleration;
|
||||
uint32_t rs = c.calculate_ramp_steps(ticks);
|
||||
uint32_t ticks_back = c.calculate_ticks(rs);
|
||||
uint32_t err = rs >= s ? rs - s : s - rs;
|
||||
uint32_t err_ticks =
|
||||
ticks >= ticks_back ? ticks - ticks_back : ticks_back - ticks;
|
||||
float speed = 16000000.0 / float(ticks);
|
||||
float speed_back = 16000000.0 / float(ticks_back);
|
||||
old_speed = speed;
|
||||
float err_speed =
|
||||
speed <= speed_back ? speed - speed_back : speed_back - speed;
|
||||
printf("%d: %d %d %f %d delta=%d delta_ticks=%d speed=%f\n", s,
|
||||
16000000 / ticks, ticks, float(sum_ticks) / 16000000.0, rs, err,
|
||||
err_ticks, err_speed);
|
||||
fprintf(gp_file, "%d %f %d %d %d %d %d %f %f\n", s,
|
||||
float(sum_ticks) / 16000000.0, 16000000 / ticks, ticks, rs, err,
|
||||
err_ticks, err_speed, ideal_speed);
|
||||
}
|
||||
fprintf(gp_file, "EOF\n");
|
||||
// fprintf(gp_file, "plot $data using 2:3 with linespoints\n");
|
||||
// fprintf(gp_file, "set terminal pngcairo size 1024,768\n");
|
||||
// fprintf(gp_file, "set output \"ramp.png\"\n");
|
||||
fprintf(gp_file, "set terminal qt\n");
|
||||
fprintf(gp_file, "set term qt size 1024,768\n");
|
||||
fprintf(gp_file,
|
||||
"set multiplot title \"Acceleration=%f max speed=%d steps/s\" layout "
|
||||
"2,2 columnsfirst margins 0.1,0.9,0.1,0.9 spacing 0.1 columnsfirst\n",
|
||||
ramp_acceleration, 16000000 / max_speed_in_ticks);
|
||||
|
||||
fprintf(gp_file, "set xlabel \"ramp steps\"\n");
|
||||
fprintf(gp_file, "set ylabel \"speed in steps/s\"\n");
|
||||
fprintf(
|
||||
gp_file,
|
||||
"plot $data using 1:3 with line title \"step to speed dependency\"\n");
|
||||
|
||||
fprintf(gp_file, "set xlabel \"ramp steps\"\n");
|
||||
fprintf(gp_file, "set ylabel \"recovered ramp steps\"\n");
|
||||
fprintf(gp_file,
|
||||
"plot $data using 1:5 with line title \"steps(speed(steps))\"\n");
|
||||
|
||||
fprintf(gp_file, "set xlabel \"time in s\"\n");
|
||||
fprintf(gp_file, "set ylabel \"speed in steps/s\"\n");
|
||||
fprintf(gp_file, "plot $data using 2:3 with line title \"speed over time\",");
|
||||
fprintf(gp_file, " $data using 2:9 with line title \"ideal speed\"\n");
|
||||
|
||||
fprintf(gp_file, "set xlabel \"time in s\"\n");
|
||||
fprintf(gp_file, "set ylabel \"speed error in steps/s\"\n");
|
||||
fprintf(gp_file, "set yrange [-10:10]\n");
|
||||
fprintf(
|
||||
gp_file,
|
||||
"plot $data using 2:8 with line title \"speed error on ramp change\",");
|
||||
fprintf(
|
||||
gp_file,
|
||||
" $data using 2:($3-$9) with line title \"speed error to ideal\"\n");
|
||||
|
||||
fprintf(gp_file, "unset multiplot\n");
|
||||
|
||||
fprintf(gp_file, "pause -1\n");
|
||||
fclose(gp_file);
|
||||
// assert(false);
|
||||
return 0;
|
||||
}
|
||||
41
extras/tests/pc_based/stubs.h
Normal file
41
extras/tests/pc_based/stubs.h
Normal file
@@ -0,0 +1,41 @@
|
||||
#ifndef STUBS_H
|
||||
#define STUBS_H
|
||||
|
||||
#define PROGMEM
|
||||
#define pgm_read_byte_near(x) (*(x))
|
||||
|
||||
// For inducing interrupts while testing
|
||||
void noInterrupts();
|
||||
void interrupts();
|
||||
void inject_fill_interrupt(int mark);
|
||||
|
||||
#define _BV(x) 0
|
||||
#define ISR(x) void x()
|
||||
#define inline
|
||||
#define micros() 0
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#define abs(x) ((x) > 0 ? (x) : -(x))
|
||||
#define min(a, b) ((a) > (b) ? (b) : (a))
|
||||
#define max(a, b) ((a) > (b) ? (a) : (b))
|
||||
|
||||
#define digitalWrite(a, b) \
|
||||
{}
|
||||
#define pinMode(a, b) \
|
||||
{}
|
||||
|
||||
extern char TCCR1A;
|
||||
extern char TCCR1B;
|
||||
extern char TCCR1C;
|
||||
extern char TIMSK1;
|
||||
extern char TIFR1;
|
||||
extern unsigned short OCR1A;
|
||||
extern unsigned short OCR1B;
|
||||
|
||||
#define test(x, msg) \
|
||||
if (!(x)) { \
|
||||
puts(msg); \
|
||||
assert(false); \
|
||||
};
|
||||
#endif
|
||||
118
extras/tests/pc_based/test_01.cpp
Normal file
118
extras/tests/pc_based/test_01.cpp
Normal file
@@ -0,0 +1,118 @@
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "FastAccelStepper.h"
|
||||
#include "StepperISR.h"
|
||||
|
||||
char TCCR1A;
|
||||
char TCCR1B;
|
||||
char TCCR1C;
|
||||
char TIMSK1;
|
||||
char TIFR1;
|
||||
unsigned short OCR1A;
|
||||
unsigned short OCR1B;
|
||||
|
||||
StepperQueue fas_queue[NUM_QUEUES];
|
||||
|
||||
void inject_fill_interrupt(int mark) {}
|
||||
void noInterrupts() {}
|
||||
void interrupts() {}
|
||||
|
||||
void init_queue() {
|
||||
fas_queue[0].read_idx = 0;
|
||||
fas_queue[0].next_write_idx = 0;
|
||||
fas_queue[1].read_idx = 0;
|
||||
fas_queue[1].next_write_idx = 0;
|
||||
}
|
||||
|
||||
void basic_test() {
|
||||
puts("basic_test...");
|
||||
init_queue();
|
||||
FastAccelStepper s = FastAccelStepper();
|
||||
assert(0 == s.getCurrentPosition());
|
||||
assert(s.isQueueEmpty());
|
||||
assert(s.isQueueEmpty());
|
||||
struct stepper_command_s cmd = {
|
||||
.ticks = 10000, .steps = 100, .count_up = true};
|
||||
int res = s.addQueueEntry(&cmd);
|
||||
assert(res == AQE_OK);
|
||||
assert(!s.isQueueEmpty());
|
||||
}
|
||||
|
||||
void queue_full() {
|
||||
puts("queue_full...");
|
||||
init_queue();
|
||||
FastAccelStepper s = FastAccelStepper();
|
||||
s.init(NULL, 0, 0);
|
||||
assert(0 == s.getCurrentPosition());
|
||||
assert(s.isQueueEmpty());
|
||||
assert(s.isQueueEmpty());
|
||||
printf("Queue read/write = %d/%d\n", fas_queue[0].read_idx,
|
||||
fas_queue[0].next_write_idx);
|
||||
struct stepper_command_s cmd = {
|
||||
.ticks = 10000, .steps = 100, .count_up = true};
|
||||
for (int i = 0; i < QUEUE_LEN - 1; i++) {
|
||||
s.addQueueEntry(&cmd);
|
||||
assert(!s.isQueueEmpty());
|
||||
assert(!s.isQueueFull());
|
||||
printf("Queue read/write = %d/%d\n", fas_queue[0].read_idx,
|
||||
fas_queue[0].next_write_idx);
|
||||
}
|
||||
s.addQueueEntry(&cmd);
|
||||
printf("Queue read/write = %d/%d\n", fas_queue[0].read_idx,
|
||||
fas_queue[0].next_write_idx);
|
||||
assert(!s.isQueueEmpty());
|
||||
assert(s.isQueueFull());
|
||||
puts("...done");
|
||||
}
|
||||
|
||||
void queue_out_of_range() {
|
||||
int8_t res;
|
||||
|
||||
puts("queue_out_of_range...");
|
||||
init_queue();
|
||||
FastAccelStepper s = FastAccelStepper();
|
||||
s.init(NULL, 0, 0);
|
||||
assert(s.isQueueEmpty());
|
||||
assert(0 == s.getCurrentPosition());
|
||||
assert(s.isQueueEmpty());
|
||||
assert(s.isQueueEmpty());
|
||||
|
||||
uint16_t ticks = s.getMaxSpeedInTicks();
|
||||
ticks = ticks - 1;
|
||||
struct stepper_command_s cmd2 = {
|
||||
.ticks = ticks, .steps = 255, .count_up = true};
|
||||
|
||||
res = s.addQueueEntry(&cmd2);
|
||||
test(res == AQE_ERROR_TICKS_TOO_LOW, "Too low ticks should trigger an error");
|
||||
assert(s.isQueueEmpty());
|
||||
|
||||
struct stepper_command_s cmd3 = {
|
||||
.ticks = MIN_CMD_TICKS - 1, .steps = 1, .count_up = true};
|
||||
|
||||
res = s.addQueueEntry(&cmd3);
|
||||
test(res == AQE_ERROR_TICKS_TOO_LOW,
|
||||
"Too short command time should trigger an error");
|
||||
assert(s.isQueueEmpty());
|
||||
}
|
||||
|
||||
void end_pos_test() {
|
||||
init_queue();
|
||||
FastAccelStepper s = FastAccelStepper();
|
||||
s.init(NULL, 0, 0);
|
||||
assert(0 == s.getPositionAfterCommandsCompleted());
|
||||
struct stepper_command_s cmd = {.ticks = 65535, .steps = 1, .count_up = true};
|
||||
|
||||
assert(AQE_OK == s.addQueueEntry(&cmd));
|
||||
assert(1 == s.getPositionAfterCommandsCompleted());
|
||||
}
|
||||
|
||||
int main() {
|
||||
// assert(sizeof(struct queue_entry) == 6);
|
||||
basic_test();
|
||||
queue_out_of_range();
|
||||
queue_full();
|
||||
end_pos_test();
|
||||
printf("TEST_01 PASSED\n");
|
||||
}
|
||||
307
extras/tests/pc_based/test_02.cpp
Normal file
307
extras/tests/pc_based/test_02.cpp
Normal file
@@ -0,0 +1,307 @@
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "FastAccelStepper.h"
|
||||
#include "StepperISR.h"
|
||||
|
||||
char TCCR1A;
|
||||
char TCCR1B;
|
||||
char TCCR1C;
|
||||
char TIMSK1;
|
||||
char TIFR1;
|
||||
unsigned short OCR1A;
|
||||
unsigned short OCR1B;
|
||||
|
||||
StepperQueue fas_queue[NUM_QUEUES];
|
||||
|
||||
void inject_fill_interrupt(int mark) {}
|
||||
void noInterrupts() {}
|
||||
void interrupts() {}
|
||||
|
||||
#include "RampChecker.h"
|
||||
|
||||
class FastAccelStepperTest {
|
||||
public:
|
||||
void init_queue() {
|
||||
fas_queue[0].read_idx = 0;
|
||||
fas_queue[1].read_idx = 0;
|
||||
fas_queue[0].next_write_idx = 0;
|
||||
fas_queue[1].next_write_idx = 0;
|
||||
}
|
||||
|
||||
void with_empty_queue() {
|
||||
printf("Test with empty queue\n");
|
||||
init_queue();
|
||||
FastAccelStepper s = FastAccelStepper();
|
||||
s.init(NULL, 0, 0);
|
||||
RampChecker rc = RampChecker();
|
||||
assert(0 == s.getCurrentPosition());
|
||||
|
||||
assert(s.isQueueEmpty());
|
||||
s.setSpeedInUs(10000);
|
||||
s.setAcceleration(100);
|
||||
s.fill_queue();
|
||||
assert(s.isQueueEmpty());
|
||||
s.move(1000);
|
||||
s.fill_queue();
|
||||
assert(!s.isQueueEmpty());
|
||||
for (int i = 0; i < 1000; i++) {
|
||||
if (false) {
|
||||
printf(
|
||||
"Loop %d: Queue read/write = %d/%d Target pos = %d, Queue End "
|
||||
"pos = %d QueueEmpty=%s\n",
|
||||
i, fas_queue[0].read_idx, fas_queue[0].next_write_idx,
|
||||
s.targetPos(), s.getPositionAfterCommandsCompleted(),
|
||||
s.isQueueEmpty() ? "yes" : "no");
|
||||
}
|
||||
if (!s.isRampGeneratorActive()) {
|
||||
break;
|
||||
}
|
||||
s.fill_queue();
|
||||
while (!s.isQueueEmpty()) {
|
||||
rc.check_section(
|
||||
&fas_queue_A.entry[fas_queue[0].read_idx & QUEUE_LEN_MASK]);
|
||||
fas_queue[0].read_idx++;
|
||||
}
|
||||
}
|
||||
test(!s.isRampGeneratorActive(), "too many commands created");
|
||||
printf("min_dt=%u\n", rc.min_dt);
|
||||
test(rc.min_dt == 160000, "max speed not reached");
|
||||
}
|
||||
|
||||
void with_pars(const char *name, int32_t steps, uint32_t travel_dt,
|
||||
uint32_t accel, bool reach_max_speed, float min_time,
|
||||
float max_time, float allowed_ramp_time_delta,
|
||||
bool call_moveTo_repeatedly = false,
|
||||
bool call_setAccelertion_repeatedly = false,
|
||||
bool alternatingAccelerationValue = false,
|
||||
bool reversing_allowed = false,
|
||||
uint32_t linear_acceleration_steps = 0,
|
||||
uint32_t jump_step = 0) {
|
||||
printf("Test %s test_with_pars steps=%d travel_dt=%d accel=%d dir=%s\n",
|
||||
name, steps, travel_dt, accel, reach_max_speed ? "CW" : "CCW");
|
||||
init_queue();
|
||||
FastAccelStepper s = FastAccelStepper();
|
||||
s.init(NULL, 0, 0);
|
||||
s.setDirectionPin(0);
|
||||
RampChecker rc = RampChecker();
|
||||
rc.reversing_allowed = reversing_allowed;
|
||||
assert(0 == s.getCurrentPosition());
|
||||
|
||||
assert(s.isQueueEmpty());
|
||||
assert(0 == s.setSpeedInUs(travel_dt));
|
||||
s.setAcceleration(accel);
|
||||
s.setLinearAcceleration(linear_acceleration_steps);
|
||||
s.setJumpStart(jump_step);
|
||||
s.fill_queue();
|
||||
assert(s.isQueueEmpty());
|
||||
s.move(steps);
|
||||
s.fill_queue();
|
||||
assert(!s.isQueueEmpty());
|
||||
float old_planned_time_in_buffer = 0;
|
||||
char fname[100];
|
||||
snprintf(fname, 100, "test_02_%s.gnuplot", name);
|
||||
rc.start_plot(fname);
|
||||
for (int i = 0; i < steps * 100; i++) {
|
||||
if (call_moveTo_repeatedly) {
|
||||
s.moveTo(steps);
|
||||
}
|
||||
if (call_setAccelertion_repeatedly) {
|
||||
if (alternatingAccelerationValue) {
|
||||
s.setAcceleration(accel + (i & 1) * 100);
|
||||
} else {
|
||||
s.setAcceleration(accel);
|
||||
}
|
||||
}
|
||||
if (true) {
|
||||
printf(
|
||||
"Loop %d: Queue read/write = %d/%d Target pos = %d, Queue End "
|
||||
"pos = %d QueueEmpty=%s\n",
|
||||
i, fas_queue[0].read_idx, fas_queue[0].next_write_idx,
|
||||
s.targetPos(), s.getPositionAfterCommandsCompleted(),
|
||||
s.isQueueEmpty() ? "yes" : "no");
|
||||
}
|
||||
if (!s.isRampGeneratorActive()) {
|
||||
break;
|
||||
}
|
||||
s.fill_queue();
|
||||
uint32_t from_dt = rc.total_ticks;
|
||||
while (!s.isQueueEmpty()) {
|
||||
rc.check_section(
|
||||
&fas_queue_A.entry[fas_queue[0].read_idx & QUEUE_LEN_MASK]);
|
||||
fas_queue[0].read_idx++;
|
||||
}
|
||||
uint32_t to_dt = rc.total_ticks;
|
||||
float planned_time = (to_dt - from_dt) * 1.0 / 16000000;
|
||||
printf("planned time in buffer: %.6fs (old=%.6fs)\n", planned_time,
|
||||
old_planned_time_in_buffer);
|
||||
// This must be ensured, so that the stepper does not run out of commands
|
||||
assert((i == 0) || (old_planned_time_in_buffer > 0.005));
|
||||
old_planned_time_in_buffer = planned_time;
|
||||
}
|
||||
// Empty the queue
|
||||
while (!s.isQueueEmpty()) {
|
||||
rc.check_section(
|
||||
&fas_queue_A.entry[fas_queue[0].read_idx & QUEUE_LEN_MASK]);
|
||||
fas_queue[0].read_idx++;
|
||||
}
|
||||
rc.finish_plot();
|
||||
printf("TEST=%s\n", name);
|
||||
test(!s.isRampGeneratorActive(), "too many commands created");
|
||||
printf("Total time %f < %f < %f ?\n", min_time,
|
||||
rc.total_ticks / 16000000.0, max_time);
|
||||
test(rc.total_ticks / 16000000.0 > min_time, "ramp too fast");
|
||||
test(rc.total_ticks / 16000000.0 < max_time, "ramp too slow");
|
||||
if (reach_max_speed) {
|
||||
printf("%d = %d ?\n", rc.min_dt, travel_dt * 16);
|
||||
test(rc.min_dt == travel_dt * 16, "max speed not reached");
|
||||
} else {
|
||||
printf("%d > %d ?\n", rc.min_dt, travel_dt * 16);
|
||||
test(rc.min_dt > travel_dt * 16, "max speed reached");
|
||||
}
|
||||
float up_time, down_time;
|
||||
if (reach_max_speed) {
|
||||
printf("Ramp time up/coast/down/total=");
|
||||
up_time = 1.0 * rc.accelerate_till / 16000000.0;
|
||||
down_time = (1.0 * rc.total_ticks - 1.0 * rc.coast_till) / 16000000.0;
|
||||
printf(" %f", 1.0 * rc.accelerate_till / 16000000.0);
|
||||
printf(" %f", 1.0 * (rc.coast_till - rc.accelerate_till) / 16000000.0);
|
||||
printf(" %f", 1.0 * (rc.total_ticks - rc.coast_till) / 16000000.0);
|
||||
printf(" %f\n", 1.0 * rc.total_ticks / 16000000.0);
|
||||
assert(rc.total_ticks > rc.coast_till);
|
||||
} else {
|
||||
printf("Ramp time up/down/total =");
|
||||
up_time = 1.0 * rc.accelerate_till / 16000000.0;
|
||||
down_time =
|
||||
(1.0 * rc.total_ticks - 1.0 * rc.accelerate_till) / 16000000.0;
|
||||
printf(" %f", 1.0 * rc.accelerate_till / 16000000.0);
|
||||
printf(" %f", 1.0 * (rc.total_ticks - rc.accelerate_till) / 16000000.0);
|
||||
printf(" %f\n", 1.0 * rc.total_ticks / 16000000.0);
|
||||
}
|
||||
// turned off
|
||||
// test(abs(up_time - down_time) <
|
||||
// 0.5 * (up_time + down_time) * allowed_ramp_time_delta,
|
||||
// "assymmetric ramp");
|
||||
#if (TEST_CREATE_QUEUE_CHECKSUM == 1)
|
||||
printf("CHECKSUM for %d/%d/%d: %d\n", steps, travel_dt, accel, s.checksum);
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
int main() {
|
||||
FastAccelStepperTest test;
|
||||
|
||||
float nc = 0.0; // if new ramp calculation is enabled
|
||||
|
||||
test.with_empty_queue();
|
||||
// steps ticks_us accel maxspeed min/max_total_time
|
||||
|
||||
// jumps in speed in real on esp32
|
||||
test.with_pars("f1", 1000, 4300, 10000, true, 4.5 - 0.2, 4.5 + 0.2, 0.5, true,
|
||||
true);
|
||||
|
||||
// ramp 2*2s, 2*200 steps, coasting: 9600steps, 48s
|
||||
test.with_pars("f2", 10000, 5000, 100, true, 2 * 2.0 + 48.0 - 0.2 - 0.4 * nc,
|
||||
2 * 2.0 + 48.0 + 0.2, 0.2);
|
||||
// ramp 2*0.02s, 2*2 steps, coasting: 1596 steps, 7.98s
|
||||
test.with_pars("f3", 1600, 5000, 10000, true, 7.94, 8.02, 0.2);
|
||||
// ramp 2*0.2s, 2*20 steps, coasting: 1560 steps, 7.8s
|
||||
test.with_pars("f4", 1600, 5000, 1000, true, 2 * 0.2 + 7.8 - 0.1,
|
||||
2 * 0.2 + 7.8 + 0.1, 0.2);
|
||||
// ramp 2*1s, 5000 steps, coasting: 5000steps, 0.5s
|
||||
test.with_pars("f5", 15000, 100, 10000, true, 2 * 1.0 + 0.5 - 0.1,
|
||||
2 * 1.0 + 0.5 + 0.1, 0.2);
|
||||
// ramp 2*0.02s, 2*2 steps, coasting: 96steps, 0.48
|
||||
test.with_pars("f6", 100, 5000, 10000, true, 2 * 0.02 + 0.48 - 0.02,
|
||||
2 * 0.02 + 0.48 + 0.02, 0.2);
|
||||
// ramp 2s, 20000 steps => only ramp 2*0.4s
|
||||
test.with_pars("f7", 1600, 50, 10000, false, 2 * 0.4 - 0.02 - 0.4 * nc,
|
||||
2 * 0.4 + 0.02, 0.2);
|
||||
// ramp 2*4s, 2*8000 steps, coasting 112000steps, 28s
|
||||
test.with_pars("f8", 128000, 250, 1000, true, 2 * 4.0 + 28.0 - 0.1 - 0.1 * nc,
|
||||
2 * 4.0 + 28.0 + 0.1, 0.2);
|
||||
// ramp 2*4s, 2*8000 steps, coasting 56000steps, 14s
|
||||
test.with_pars("f9", 72000, 250, 1000, true, 2 * 4.0 + 14.0 - 0.1 - 0.1 * nc,
|
||||
2 * 4.0 + 14.0 + 0.1, 0.2);
|
||||
// ramp 2*4s, 2*8000 steps, coasting 28000steps, 7s
|
||||
test.with_pars("f10", 44000, 250, 1000, true, 2 * 4.0 + 7.0 - 0.1 - 0.1 * nc,
|
||||
2 * 4.0 + 7.0 + 0.1, 0.2);
|
||||
// ramp 2*4s, 2*8000 steps, coasting 2steps, 0.0005s
|
||||
// fails with 16030
|
||||
test.with_pars("f11", 16040, 250, 1000, true, 2 * 4.0 + 0.0 - 0.1 - 0.1 * nc,
|
||||
2 * 4.0 + 0.1 + 0.1, 0.2);
|
||||
// ramp 2*50s => 2*1s
|
||||
test.with_pars("f12", 1000, 20, 1000, false, 2 * 1.0 - 0.15, 2 * 1.0 + 0.1,
|
||||
0.2);
|
||||
|
||||
// The following five ramps are too fast.
|
||||
// The first step should come after ~0.6s and
|
||||
// the second after 0.89s. Implementation issues first step immediately
|
||||
// with pause to 2nd step of 0.36s (actually 0.315s).
|
||||
// So the first steps are issued within 0.36s instead of 0.89s.
|
||||
//
|
||||
// The implementation issues in addition the last two steps with 0.315s pause
|
||||
float rd = 0.7; // rd means ramp deviation
|
||||
//
|
||||
// ramp 2*50s, thus with 500steps max speed not reached. 250steps need 10s
|
||||
test.with_pars("f13", 500, 4000, 5, false, 20.0 - rd - 0.1 - 1.4 * nc,
|
||||
20.0 - rd + 0.2, 0.2);
|
||||
test.with_pars("f14", 2000, 4000, 5, false, 40.0 - rd - 0.1 - 1.7 * nc,
|
||||
40.0 - rd + 0.2, 0.2);
|
||||
// ramp 2*50s with 2*6250 steps => 100 steps at max speed using 0.4s
|
||||
test.with_pars("f15", 12600, 4000, 5, true, 100.0 + 0.4 - 0.3 - rd - 2.3 * nc,
|
||||
100.0 + 0.4 - rd + 0.24, 0.2);
|
||||
// ramp 2*50s with 2*6250 steps => 4000 steps at max speed using 16s
|
||||
test.with_pars("f16", 16500, 4000, 5, true, 116.0 - 0.3 - rd - 2.2 * nc,
|
||||
116.0 + 0.23 - rd, 0.2);
|
||||
// slow ramp: 2*50steps, 2*10s
|
||||
rd = 1.4;
|
||||
test.with_pars("f17", 100, 40, 1, false, 20.0 - 0.1 - rd - 2.0 * nc,
|
||||
20.0 + 0.1 - rd, 1.0);
|
||||
|
||||
// jumps in speed in real => WORKS NOW
|
||||
test.with_pars("f18", 256000, 40, 5000, true, 15.2 - 0.1, 15.2 + 0.2, 0.2);
|
||||
|
||||
// ramp time 625s, 7812500 steps
|
||||
// test.with_pars("f19", 2000000, 40, 40, false, 2*223.0, 2*223.0);
|
||||
|
||||
// name, steps, travel_dt, accel, reach_max_speed, min_time, max_time,
|
||||
// allowed_ramp_time_delta slow ramp time Those are anomalies (see github
|
||||
// issue #8) on avr, but not on PC
|
||||
// test.with_pars("f20", 50000, 270000, 10, true, 62.0, 63.0, 1.0);
|
||||
test.with_pars("f20", 10, 1000000, 1, true, 9.9, 10.1, 1.0);
|
||||
|
||||
// no ramp time, just constant run time
|
||||
test.with_pars("f21", 15000, 4000, 100000, true, 50.9, 60.1, 0.1);
|
||||
test.with_pars("f22", 14634, 4100, 100000, true, 50.9, 60.1, 0.1);
|
||||
|
||||
// single step
|
||||
test.with_pars("f23", 1, 100, 1000, false, 0.02, 0.05, 0.1);
|
||||
|
||||
// try to identify issue #40
|
||||
test.with_pars("f24a", 5000, 200, 9999, true, 1.48 + 0.1 * nc, 1.5 + 0.1 * nc,
|
||||
0.1, true, true, false, true);
|
||||
test.with_pars("f24b", 5000, 200, 9999, true, 1.48 - 0.04 * nc,
|
||||
1.50 - 0.04 * nc, 0.1, false, false, false);
|
||||
test.with_pars("f24c", 5000, 200, 9999, true, 1.48 - 0.04 * nc,
|
||||
1.50 - 0.04 * nc, 0.1, false, false, true);
|
||||
test.with_pars("f24d", 5000, 200, 9999, true, 1.48 - 0.04 * nc,
|
||||
1.50 - 0.04 * nc, 0.1, true, false, true);
|
||||
|
||||
test.with_pars("f25", 1000, 40, 0x7fffffff, true, 0.039, 0.041, 0.1);
|
||||
|
||||
// very short ramp. detected by esp32_hw_based tests seq_06.sh
|
||||
test.with_pars("seq_06.sh", 54, 40, 1000000, false, 0.012, 0.018, 0.1);
|
||||
|
||||
// ramp with jump start
|
||||
test.with_pars("f5_jumpstart", 15000, 100, 10000, true, 2 * 1.0 + 0.0 - 0.1,
|
||||
2 * 1.0 + 0.5 + 0.1, 0.2, false, false, false, false, 0, 100);
|
||||
|
||||
// ramp with linea acceleration
|
||||
test.with_pars("f5_linear_a", 15000, 100, 10000, true, 3, 4, 0.2, false,
|
||||
false, false, false, 1000);
|
||||
|
||||
printf("TEST_02 PASSED\n");
|
||||
return 0;
|
||||
}
|
||||
438
extras/tests/pc_based/test_03.h
Normal file
438
extras/tests/pc_based/test_03.h
Normal file
@@ -0,0 +1,438 @@
|
||||
#include <math.h>
|
||||
|
||||
struct const_tab {
|
||||
uint32_t val_nom;
|
||||
uint32_t val_denom;
|
||||
bool squared;
|
||||
pmf_logarithmic c;
|
||||
};
|
||||
|
||||
bool perform_test() {
|
||||
#define NR_OF_CONSTANTS 13
|
||||
static const struct const_tab constants[NR_OF_CONSTANTS] = {
|
||||
{1, 1, false, PMF_CONST_1},
|
||||
{16000000, 1, false, PMF_CONST_16E6},
|
||||
{3, 2, false, PMF_CONST_3_DIV_2},
|
||||
{500, 1, false, PMF_CONST_500},
|
||||
{1000, 1, false, PMF_CONST_1000},
|
||||
{2000, 1, false, PMF_CONST_2000},
|
||||
{32000, 1, false, PMF_CONST_32000},
|
||||
{11313708, 1, false, PMF_CONST_16E6_DIV_SQRT_OF_2},
|
||||
{21000000, 1, false, PMF_CONST_21E6},
|
||||
{42000, 1, false, PMF_CONST_42000},
|
||||
// The additional 4000 to make the test case pass
|
||||
{14849242 + 4000, 1, false, PMF_CONST_21E6_DIV_SQRT_OF_2},
|
||||
{16000000, 2, true, PMF_CONST_128E12}, // (16e6)^2 / 2
|
||||
{21000000, 2, true, PMF_CONST_2205E11} // (21e6)^2 / 2
|
||||
};
|
||||
uint16_t l1;
|
||||
pmf_logarithmic p1;
|
||||
|
||||
trace("Check leading_zeros()");
|
||||
for (int16_t x_8 = 0; x_8 <= 255; x_8++) {
|
||||
uint8_t leading = leading_zeros(x_8);
|
||||
test(x_8 < (1 << (8 - leading)), "leading zeros too much");
|
||||
test(x_8 >= (0x80 >> leading), "leading zeros too less");
|
||||
}
|
||||
|
||||
trace("Check conversion u8 <=> pmfl");
|
||||
p1 = pmfl_from((uint8_t)1);
|
||||
l1 = pmfl_to_u16(p1);
|
||||
xprintf("%x %d\n", p1, l1);
|
||||
test(p1 == 0x0000, "value 1");
|
||||
test(l1 == 1, "value 1");
|
||||
|
||||
trace("Check conversion u8 <=> pmfl by shift 8bit");
|
||||
for (uint8_t n = 1; n < 8; n++) {
|
||||
uint8_t v = 1 << n;
|
||||
p1 = pmfl_from((uint8_t)v);
|
||||
l1 = pmfl_to_u16(p1);
|
||||
xprintf("8bit: %x %d\n", p1, l1);
|
||||
test(p1 == ((int16_t)n) << 9, "value");
|
||||
test(l1 == v, "value");
|
||||
}
|
||||
|
||||
trace("Check conversion u8 <=> pmfl by shift 16bit");
|
||||
for (uint8_t n = 1; n < 16; n++) {
|
||||
uint16_t v = 1 << n;
|
||||
p1 = pmfl_from((uint16_t)v);
|
||||
l1 = pmfl_to_u16(p1);
|
||||
xprintf("16bit: %x %d\n", p1, l1);
|
||||
test(p1 == ((int16_t)n) << 9, "value");
|
||||
test(l1 == v, "value");
|
||||
}
|
||||
|
||||
trace("Check conversion u8 <=> pmfl by shift 32bit");
|
||||
for (uint8_t n = 1; n < 32; n++) {
|
||||
uint32_t v = 1;
|
||||
v <<= n;
|
||||
p1 = pmfl_from((uint32_t)v);
|
||||
uint32_t res = pmfl_to_u32(p1);
|
||||
xprintf("32bit: %x %u\n", p1, res);
|
||||
test(p1 == (((int16_t)n) << 9), "value");
|
||||
test(res == v, "value");
|
||||
}
|
||||
|
||||
trace("Check conversion u8 <=> pmfl for all values");
|
||||
for (uint8_t x_8 = 255; x_8 > 0; x_8--) {
|
||||
p1 = pmfl_from((uint8_t)x_8);
|
||||
uint16_t res_16 = pmfl_to_u16(p1);
|
||||
if (res_16 != x_8) {
|
||||
xprintf("%u => %x => %u\n", x_8, p1, res_16);
|
||||
}
|
||||
test(res_16 == x_8, "conversion error from uint8_t and back to uint16_t");
|
||||
}
|
||||
|
||||
for (uint8_t n = 1; n <= 8; n++) {
|
||||
for (uint8_t x_8 = 255; x_8 > 0; x_8--) {
|
||||
uint16_t x_16 = x_8;
|
||||
x_16 <<= n;
|
||||
p1 = pmfl_from((uint8_t)x_8);
|
||||
p1 = pmfl_shl(p1, n);
|
||||
uint16_t res_16 = pmfl_to_u16(p1);
|
||||
uint16_t delta = x_16 - res_16;
|
||||
if (res_16 > x_16) {
|
||||
delta = res_16 - x_16;
|
||||
}
|
||||
uint16_t limit = 1;
|
||||
limit <<= n - 1;
|
||||
if (delta > limit) {
|
||||
xprintf("%u: %u => %x => %u, shifted: %d\n", x_8, x_16, p1, res_16, n);
|
||||
}
|
||||
test(delta <= limit,
|
||||
"conversion error from uint8_t and back to uint16_t with shift");
|
||||
}
|
||||
}
|
||||
|
||||
for (uint8_t n = 1; n <= 24; n++) {
|
||||
for (uint8_t x_8 = 255; x_8 > 0; x_8--) {
|
||||
uint32_t x_32 = x_8;
|
||||
x_32 <<= n;
|
||||
p1 = pmfl_from((uint8_t)x_8);
|
||||
p1 = pmfl_shl(p1, n);
|
||||
uint32_t res_32 = pmfl_to_u32(p1);
|
||||
uint32_t delta = x_32 - res_32;
|
||||
if (res_32 > x_32) {
|
||||
delta = res_32 - x_32;
|
||||
}
|
||||
uint32_t limit = 1;
|
||||
limit <<= n - 1;
|
||||
if (delta > limit) {
|
||||
xprintf("%u: %u => %x => %u, shifted: %d\n", x_8, x_32, p1, res_32, n);
|
||||
}
|
||||
test(delta <= limit,
|
||||
"conversion error from uint8_t and back to uint32_t with shift");
|
||||
}
|
||||
}
|
||||
trace("Check conversion u16 <=> pmfl");
|
||||
uint16_t limit = 0x100;
|
||||
uint16_t trigger_16 = 0x8000;
|
||||
for (uint16_t x_16 = 0xffff; x_16 > 0; x_16--) {
|
||||
if ((x_16 & trigger_16) == 0) {
|
||||
limit >>= 1;
|
||||
trigger_16 >>= 1;
|
||||
}
|
||||
pmf_logarithmic p = pmfl_from((uint16_t)x_16);
|
||||
uint16_t res_16 = pmfl_to_u16(p);
|
||||
uint16_t delta = x_16 - res_16;
|
||||
if (res_16 > x_16) {
|
||||
delta = res_16 - x_16;
|
||||
}
|
||||
if (delta > limit) {
|
||||
xprintf("%x => %x => %x (limit=%x)\n", x_16, p, res_16, limit);
|
||||
}
|
||||
test(delta <= limit, "conversion error from uint16_t and back to uint16_t");
|
||||
}
|
||||
|
||||
for (uint8_t n = 1; n <= 16; n++) {
|
||||
uint32_t msb = 32768;
|
||||
for (uint16_t x_16 = 65535; x_16 > 256; x_16--) {
|
||||
if ((x_16 & msb) == 0) {
|
||||
msb >>= 1;
|
||||
}
|
||||
uint32_t x_32 = x_16;
|
||||
x_32 <<= n;
|
||||
p1 = pmfl_from((uint16_t)x_16);
|
||||
p1 = pmfl_shl(p1, n);
|
||||
uint32_t res_32 = pmfl_to_u32(p1);
|
||||
uint32_t delta = x_32 - res_32;
|
||||
uint32_t limit = (msb << n) >> 8;
|
||||
limit += limit >> 2;
|
||||
if (res_32 > x_32) {
|
||||
delta = res_32 - x_32;
|
||||
}
|
||||
if (delta > limit) {
|
||||
xprintf("%u: %u => %x => %u, shifted: %d, delta: %d > %d\n", x_16, x_32,
|
||||
p1, res_32, n, delta, limit);
|
||||
}
|
||||
test(delta <= limit,
|
||||
"conversion error from uint16_t and back to uint32_t with shift");
|
||||
}
|
||||
}
|
||||
|
||||
p1 = pmfl_from((uint32_t)0x10000);
|
||||
test(pmfl_to_u16(p1) == 0xffff, "wrong overflow 16bit");
|
||||
p1 = pmfl_from((uint32_t)0x80000000);
|
||||
p1 = pmfl_shl(p1, 1);
|
||||
test(pmfl_to_u32(p1) == 0xffffffff, "wrong overflow 32bit");
|
||||
|
||||
#ifndef SIMULATOR
|
||||
trace("Check conversion u32 <=> pmfl");
|
||||
uint32_t trigger_32 = 0x80000000;
|
||||
uint32_t delta_32 = 0x01000000;
|
||||
for (uint32_t x_32 = 0xffffffff; x_32 > 0; x_32 -= delta_32) {
|
||||
if ((x_32 & trigger_32) == 0) {
|
||||
trigger_32 >>= 1;
|
||||
delta_32 >>= 1;
|
||||
if (delta_32 == 0) {
|
||||
delta_32 = 1;
|
||||
}
|
||||
}
|
||||
pmf_logarithmic px = pmfl_from((uint32_t)x_32);
|
||||
uint32_t res_32 = pmfl_to_u32(px);
|
||||
uint32_t delta = x_32 - res_32;
|
||||
if (res_32 > x_32) {
|
||||
delta = res_32 - x_32;
|
||||
}
|
||||
if (delta > delta_32 + 1) {
|
||||
xprintf("%x => %x => %x (delta=%x > %x)\n", x_32, px, res_32, delta,
|
||||
delta_32);
|
||||
}
|
||||
test(delta <= delta_32 + 1,
|
||||
"conversion error from uint32_t and back to uint32_t");
|
||||
}
|
||||
|
||||
trace("Check multiply");
|
||||
for (int16_t sa = -40; sa <= 40; sa++) {
|
||||
for (uint32_t a_32 = 1; a_32 <= 0x1ff; a_32++) {
|
||||
for (uint32_t b_32 = 1; b_32 <= 0x1ff; b_32++) {
|
||||
p1 = pmfl_from(a_32);
|
||||
pmf_logarithmic p2 = pmfl_from(b_32);
|
||||
if (sa > 0) {
|
||||
p1 = pmfl_shl(p1, sa);
|
||||
} else if (sa < 0) {
|
||||
p1 = pmfl_shr(p1, -sa);
|
||||
}
|
||||
pmf_logarithmic p = pmfl_multiply(p1, p2);
|
||||
if (sa > 0) {
|
||||
p = pmfl_shr(p, sa);
|
||||
} else if (sa < 0) {
|
||||
p = pmfl_shl(p, -sa);
|
||||
}
|
||||
uint32_t res = pmfl_to_u32(p);
|
||||
uint32_t real_res = a_32 * b_32;
|
||||
uint32_t repr_real = pmfl_to_u32(pmfl_from(real_res));
|
||||
uint32_t delta = res - repr_real;
|
||||
if (res < repr_real) {
|
||||
delta = repr_real - res;
|
||||
}
|
||||
uint32_t limit = real_res >> 7;
|
||||
if (delta > limit) {
|
||||
xprintf("%d*%d=%d ~ %d =?= %d, diff=%d\n", a_32, b_32, a_32 * b_32,
|
||||
repr_real, res, (int32_t)res - (int32_t)repr_real);
|
||||
}
|
||||
test(delta <= limit, "pmfl_multiply error");
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
trace("Check pmf constants");
|
||||
bool error = false;
|
||||
for (uint8_t i = 0; i < NR_OF_CONSTANTS; i++) {
|
||||
const struct const_tab *dut = &constants[i];
|
||||
pmf_logarithmic val = pmfl_from(dut->val_nom);
|
||||
if (dut->squared) {
|
||||
val += val;
|
||||
}
|
||||
if (dut->val_denom > 1) {
|
||||
pmf_logarithmic val_denom = pmfl_from(dut->val_denom);
|
||||
val -= val_denom;
|
||||
}
|
||||
pmf_logarithmic c = dut->c;
|
||||
if (c != val) {
|
||||
xprintf("(%d/%d)^%d => %x != %x\n", dut->val_nom, dut->val_denom,
|
||||
dut->squared ? 2 : 1, val, c);
|
||||
error = true;
|
||||
}
|
||||
}
|
||||
test(!error, "constants");
|
||||
|
||||
trace("Check rsqrt");
|
||||
for (int16_t sa = -20; sa <= 20; sa++) {
|
||||
for (uint32_t a_32 = 1; a_32 <= 0x1ff; a_32++) {
|
||||
p1 = pmfl_from(a_32);
|
||||
if (sa > 0) {
|
||||
p1 = pmfl_shl(p1, sa);
|
||||
} else if (sa < 0) {
|
||||
p1 = pmfl_shr(p1, -sa);
|
||||
}
|
||||
pmf_logarithmic p = pmfl_rsqrt(p1);
|
||||
pmf_logarithmic pe =
|
||||
pmfl_multiply(p1, pmfl_multiply(p, p)); // sqrt not yet tested
|
||||
// pe should be approximately 1
|
||||
uint32_t res = pmfl_to_u32(pmfl_shl(pe, 16));
|
||||
int32_t diff = (int32_t)res - 0x10000;
|
||||
if (abs(diff) > 384) {
|
||||
xprintf("a=%d pmfl(x)=%x pmfl(rsqrt(x))=%x pmfl(rsqrt(x)^2*x)=%x ",
|
||||
a_32, p1, p, pe);
|
||||
xprintf("shift=%d rsqrt(%d)^2*%d*0x10000=%x, diff=%d\n", sa, a_32, a_32,
|
||||
res, diff);
|
||||
}
|
||||
test(abs(diff) <= 384, "rsqrt error");
|
||||
}
|
||||
}
|
||||
|
||||
trace("Check square");
|
||||
for (int16_t sa = -20; sa <= 20; sa++) {
|
||||
for (uint32_t a_32 = 1; a_32 <= 0x1ff; a_32++) {
|
||||
p1 = pmfl_from(a_32);
|
||||
if (sa > 0) {
|
||||
p1 = pmfl_shl(p1, sa);
|
||||
} else if (sa < 0) {
|
||||
p1 = pmfl_shr(p1, -sa);
|
||||
}
|
||||
pmf_logarithmic p = pmfl_square(p1);
|
||||
pmf_logarithmic pe = pmfl_multiply(p1, p1);
|
||||
int32_t diff = (int32_t)p - (int32_t)pe;
|
||||
if (diff > 1) { // square has better precision than multiply
|
||||
xprintf("a=%d pmfl(x)=%x pmfl(square(x))=%x pmfl(x*x)=%x ", a_32, p1,
|
||||
p, pe);
|
||||
xprintf("shift=%d, diff=%d\n", sa, 0);
|
||||
}
|
||||
test(diff <= 1, "square error");
|
||||
}
|
||||
}
|
||||
|
||||
trace("Check reciprocal square");
|
||||
for (int16_t sa = -20; sa <= 20; sa++) {
|
||||
for (uint32_t a_32 = 1; a_32 <= 0x1ff; a_32++) {
|
||||
p1 = pmfl_from(a_32);
|
||||
if (sa > 0) {
|
||||
p1 = pmfl_shl(p1, sa);
|
||||
} else if (sa < 0) {
|
||||
p1 = pmfl_shr(p1, -sa);
|
||||
}
|
||||
pmf_logarithmic p = pmfl_rsquare(p1);
|
||||
|
||||
pmf_logarithmic pe = pmfl_multiply(p, pmfl_square(p1));
|
||||
// pe should be approximately 1
|
||||
uint32_t res = pmfl_to_u32(pmfl_shl(pe, 16));
|
||||
int32_t diff = (int32_t)res - 0x10000;
|
||||
if (abs(diff) > 384) {
|
||||
xprintf("a=%d pmfl(x)=%x pmfl(rsquare(x))=%x pmfl(rsquare(x)*x^2)=%x ",
|
||||
a_32, p1, p, pe);
|
||||
xprintf("shift=%d rsquare(%d)*%d^2*0x10000=%x, diff=%d\n", sa, a_32,
|
||||
a_32, res, diff);
|
||||
}
|
||||
test(abs(diff) <= 384, "rsquare error");
|
||||
}
|
||||
}
|
||||
|
||||
trace("Check reciprocal");
|
||||
for (int16_t sa = -20; sa <= 20; sa++) {
|
||||
for (uint32_t a_32 = 1; a_32 <= 0x1ff; a_32++) {
|
||||
p1 = pmfl_from(a_32);
|
||||
if (sa > 0) {
|
||||
p1 = pmfl_shl(p1, sa);
|
||||
} else if (sa < 0) {
|
||||
p1 = pmfl_shr(p1, -sa);
|
||||
}
|
||||
pmf_logarithmic p = pmfl_reciprocal(p1);
|
||||
|
||||
pmf_logarithmic pe = pmfl_multiply(p, p1);
|
||||
// xe should be approximately 1
|
||||
uint32_t res = pmfl_to_u32(pmfl_shl(pe, 16));
|
||||
int32_t diff = (int32_t)res - 0x10000;
|
||||
if (abs(diff) > 384) {
|
||||
xprintf(
|
||||
"a=%d pmfl(x)=%x pmfl(reciprocal(x))=%x pmfl(reciprocal(x)*x)=%x ",
|
||||
a_32, p1, p, pe);
|
||||
xprintf("shift=%d reciprocal(%d)*%d*0x10000=%x, diff=%d\n", sa, a_32,
|
||||
a_32, res, diff);
|
||||
}
|
||||
test(abs(diff) <= 384, "reciprocal error");
|
||||
}
|
||||
}
|
||||
|
||||
trace("Check specific use cases");
|
||||
pmf_logarithmic x, x1, x2;
|
||||
x1 = pmfl_from((uint32_t)0x0ffff);
|
||||
x2 = pmfl_from((uint32_t)0x10100);
|
||||
x = pmfl_multiply(x1, x2);
|
||||
unsigned long back = pmfl_to_u32(x);
|
||||
test(back == 0xffffffff, "overflow not catched");
|
||||
|
||||
x1 = pmfl_from((uint32_t)0x5555);
|
||||
x2 = pmfl_from((uint32_t)0x0055);
|
||||
x = pmfl_divide(x1, x2);
|
||||
back = pmfl_to_u32(x);
|
||||
xprintf("%x/%x=%x (back=%ld)\n", x1, x2, x, back);
|
||||
test(back == 0x0101, "wrong division");
|
||||
|
||||
x1 = pmfl_from((uint32_t)0xf455);
|
||||
x2 = pmfl_from((uint32_t)0x0030);
|
||||
x = pmfl_divide(x1, x2);
|
||||
back = pmfl_to_u32(x);
|
||||
back--; // result is too high by one
|
||||
xprintf("%x/%x=%x (%ld) f455/0030=%d\n", x1, x2, x, back, 0xf455 / 0x30);
|
||||
test((back * 0x0030) <= 0xf455, "wrong division 1");
|
||||
test((back * 0x0031) > 0xf455, "wrong division 2");
|
||||
|
||||
x1 = pmfl_from((uint32_t)0xf4555);
|
||||
x = pmfl_shl(x1, 4);
|
||||
back = pmfl_to_u32(x);
|
||||
xprintf("%x => %x (%lx)\n", x1, x, back);
|
||||
test(back == 0xf44000, "wrong pmfl_shl");
|
||||
x1 = pmfl_from((uint32_t)0xf4555);
|
||||
x = pmfl_shr(x1, 4);
|
||||
back = pmfl_to_u32(x);
|
||||
xprintf("%x => %x (%lx)\n", x1, x, back);
|
||||
test(back == 0xf440, "wrong pmfl_shr");
|
||||
|
||||
x1 = pmfl_from((uint32_t)250);
|
||||
x2 = pmfl_from((uint32_t)10000);
|
||||
x = pmfl_divide(x1, x2);
|
||||
back = pmfl_to_u32(x);
|
||||
xprintf("%x/%x=%x (%ld)\n", x1, x2, x, back);
|
||||
test(back == 0, "pmfl_divide 1");
|
||||
x = pmfl_multiply(x, x2);
|
||||
back = pmfl_to_u32(x);
|
||||
xprintf("%x/%x*%x=%x (%ld)\n", x1, x2, x2, x, back);
|
||||
back--; // value is one too high
|
||||
test(back == 249, "pmfl_divide 2");
|
||||
|
||||
x1 = pmfl_from((uint32_t)250);
|
||||
x2 = pmfl_from((uint32_t)10000);
|
||||
x = pmfl_divide(x1, x2);
|
||||
back = pmfl_to_u32(x);
|
||||
xprintf("%x/%x=%x (%ld)\n", x1, x2, x, back);
|
||||
test(back == 0, "pmfl_divide");
|
||||
x = pmfl_shl(x, 10);
|
||||
back = pmfl_to_u32(x);
|
||||
xprintf("pmfl_shl(%x/%x,10)=%x (%ld)\n", x1, x2, x, back);
|
||||
test(back == 25, "pmfl_divide/pmfl_shl");
|
||||
|
||||
x1 = pmfl_from((uint32_t)1600);
|
||||
x2 = pmfl_from((uint32_t)1000000);
|
||||
x = pmfl_divide(x1, x2);
|
||||
back = pmfl_to_u32(x);
|
||||
xprintf("%x/%x=%x (%ld)\n", x1, x2, x, back);
|
||||
test(back == 0, "pmfl_divide");
|
||||
x = pmfl_shl(x, 20);
|
||||
back = pmfl_to_u32(x);
|
||||
xprintf("pmfl_shl(%x/%x,20)=%x (%ld)\n", x1, x2, x, back);
|
||||
test(back + 2 == 1678, "pmfl_divide/pmfl_shl");
|
||||
x = pmfl_shr(x, 20);
|
||||
back = pmfl_to_u32(x);
|
||||
xprintf("pmfl_shr(pmfl_shl(%x/%x,20),20)=%x (%ld)\n", x1, x2, x, back);
|
||||
test(back == 0, "pmfl_divide/pmfl_shl");
|
||||
|
||||
x1 = pmf_logarithmic((uint32_t)1500);
|
||||
x = pmfl_pow_div_3(x1);
|
||||
xprintf("%d/3=%d\n", x1, x);
|
||||
// +1 is deviation
|
||||
test(x + 1 == 500, "pmfl_pow_div_3");
|
||||
|
||||
return (error_cnt == 0);
|
||||
}
|
||||
169
extras/tests/pc_based/test_04.cpp
Normal file
169
extras/tests/pc_based/test_04.cpp
Normal file
@@ -0,0 +1,169 @@
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "FastAccelStepper.h"
|
||||
#include "StepperISR.h"
|
||||
|
||||
char TCCR1A;
|
||||
char TCCR1B;
|
||||
char TCCR1C;
|
||||
char TIMSK1;
|
||||
char TIFR1;
|
||||
unsigned short OCR1A;
|
||||
unsigned short OCR1B;
|
||||
|
||||
StepperQueue fas_queue[NUM_QUEUES];
|
||||
|
||||
void inject_fill_interrupt(int mark) {}
|
||||
void noInterrupts() {}
|
||||
void interrupts() {}
|
||||
|
||||
#include "RampChecker.h"
|
||||
|
||||
class FastAccelStepperTest {
|
||||
public:
|
||||
void init_queue() {
|
||||
fas_queue[0].read_idx = 0;
|
||||
fas_queue[1].read_idx = 0;
|
||||
fas_queue[0].next_write_idx = 0;
|
||||
fas_queue[1].next_write_idx = 0;
|
||||
}
|
||||
|
||||
void speed_increase() {
|
||||
puts("Test test_speed_increase");
|
||||
init_queue();
|
||||
FastAccelStepper s = FastAccelStepper();
|
||||
s.init(NULL, 0, 0);
|
||||
RampChecker rc = RampChecker();
|
||||
assert(0 == s.getCurrentPosition());
|
||||
|
||||
int32_t steps = 10000;
|
||||
|
||||
// Increase speed to 400, then further to 300
|
||||
// Identified bug was a fast jump to 300 without acceleration
|
||||
assert(s.isQueueEmpty());
|
||||
s.setSpeedInUs(400);
|
||||
s.setAcceleration(1000);
|
||||
s.fill_queue();
|
||||
assert(s.isQueueEmpty());
|
||||
s.move(steps);
|
||||
s.fill_queue();
|
||||
assert(!s.isQueueEmpty());
|
||||
float old_planned_time_in_buffer = 0;
|
||||
int speed_increased = false;
|
||||
for (int i = 0; i < steps; i++) {
|
||||
if (!speed_increased && (s.getCurrentPosition() >= 5000)) {
|
||||
puts("Change speed");
|
||||
s.fill_queue(); // ensure queue is not empty
|
||||
speed_increased = true;
|
||||
s.setSpeedInUs(300);
|
||||
s.move(steps);
|
||||
}
|
||||
if (true) {
|
||||
printf(
|
||||
"Loop %d: Queue read/write = %d/%d Target pos = %d, Queue End "
|
||||
"pos = %d QueueEmpty=%s\n",
|
||||
i, fas_queue[0].read_idx, fas_queue[0].next_write_idx,
|
||||
s.targetPos(), s.getPositionAfterCommandsCompleted(),
|
||||
s.isQueueEmpty() ? "yes" : "no");
|
||||
}
|
||||
if (!s.isRampGeneratorActive()) {
|
||||
break;
|
||||
}
|
||||
s.fill_queue();
|
||||
uint32_t from_dt = rc.total_ticks;
|
||||
while (!s.isQueueEmpty()) {
|
||||
rc.check_section(
|
||||
&fas_queue[0].entry[fas_queue[0].read_idx & QUEUE_LEN_MASK]);
|
||||
fas_queue[0].read_idx++;
|
||||
}
|
||||
uint32_t to_dt = rc.total_ticks;
|
||||
float planned_time = (to_dt - from_dt) * 1.0 / 16000000;
|
||||
printf("planned time in buffer: %.6fs\n", planned_time);
|
||||
// This must be ensured, so that the stepper does not run out of commands
|
||||
assert((i == 0) || (old_planned_time_in_buffer > 0.005));
|
||||
old_planned_time_in_buffer = planned_time;
|
||||
}
|
||||
test(!s.isRampGeneratorActive(), "too many commands created");
|
||||
printf("Total time %f\n", rc.total_ticks / 16000000.0);
|
||||
#if (TEST_CREATE_QUEUE_CHECKSUM == 1)
|
||||
printf("CHECKSUM for %d/%d/%d: %d\n", steps, travel_dt, accel, s.checksum);
|
||||
#endif
|
||||
}
|
||||
|
||||
void speed_decrease() {
|
||||
puts("Test test_speed_decrease");
|
||||
init_queue();
|
||||
FastAccelStepper s = FastAccelStepper();
|
||||
s.init(NULL, 0, 0);
|
||||
RampChecker rc = RampChecker();
|
||||
assert(0 == s.getCurrentPosition());
|
||||
|
||||
int32_t steps = 10000;
|
||||
|
||||
// Increase speed to 400, then further to 300
|
||||
// Identified bug was a fast jump to 300 without acceleration
|
||||
assert(s.isQueueEmpty());
|
||||
s.setSpeedInUs(400);
|
||||
s.setAcceleration(1000);
|
||||
s.fill_queue();
|
||||
assert(s.isQueueEmpty());
|
||||
s.move(steps);
|
||||
s.fill_queue();
|
||||
assert(!s.isQueueEmpty());
|
||||
float old_planned_time_in_buffer = 0;
|
||||
int speed_decreased = false;
|
||||
uint32_t count_state_dec = 0;
|
||||
for (int i = 0; i < steps; i++) {
|
||||
if (!speed_decreased && (s.getCurrentPosition() >= 5000)) {
|
||||
puts("Change speed");
|
||||
s.fill_queue(); // ensure queue is not empty
|
||||
speed_decreased = true;
|
||||
s.setSpeedInUs(500);
|
||||
s.move(steps);
|
||||
}
|
||||
if (true) {
|
||||
printf(
|
||||
"Loop %d: Queue read/write = %d/%d Target pos = %d, Queue End "
|
||||
"pos = %d QueueEmpty=%s\n",
|
||||
i, fas_queue[0].read_idx, fas_queue[0].next_write_idx,
|
||||
s.targetPos(), s.getPositionAfterCommandsCompleted(),
|
||||
s.isQueueEmpty() ? "yes" : "no");
|
||||
}
|
||||
if (!s.isRampGeneratorActive()) {
|
||||
break;
|
||||
}
|
||||
s.fill_queue();
|
||||
if ((s.rampState() & RAMP_STATE_MASK) == RAMP_STATE_DECELERATE) {
|
||||
count_state_dec++;
|
||||
}
|
||||
uint32_t from_dt = rc.total_ticks;
|
||||
while (!s.isQueueEmpty()) {
|
||||
rc.check_section(
|
||||
&fas_queue[0].entry[fas_queue[0].read_idx & QUEUE_LEN_MASK]);
|
||||
fas_queue[0].read_idx++;
|
||||
}
|
||||
uint32_t to_dt = rc.total_ticks;
|
||||
float planned_time = (to_dt - from_dt) * 1.0 / 16000000;
|
||||
printf("planned time in buffer: %.6fs\n", planned_time);
|
||||
// This must be ensured, so that the stepper does not run out of commands
|
||||
assert((i == 0) || (old_planned_time_in_buffer > 0.005));
|
||||
old_planned_time_in_buffer = planned_time;
|
||||
}
|
||||
test(!s.isRampGeneratorActive(), "too many commands created");
|
||||
test(count_state_dec > 10, "no deceleration to new speed");
|
||||
printf("Total time %f\n", rc.total_ticks / 16000000.0);
|
||||
#if (TEST_CREATE_QUEUE_CHECKSUM == 1)
|
||||
printf("CHECKSUM for %d/%d/%d: %d\n", steps, travel_dt, accel, s.checksum);
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
int main() {
|
||||
FastAccelStepperTest test;
|
||||
test.speed_increase();
|
||||
test.speed_decrease();
|
||||
printf("TEST_04 PASSED\n");
|
||||
return 0;
|
||||
}
|
||||
160
extras/tests/pc_based/test_05.cpp
Normal file
160
extras/tests/pc_based/test_05.cpp
Normal file
@@ -0,0 +1,160 @@
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "FastAccelStepper.h"
|
||||
#include "StepperISR.h"
|
||||
|
||||
char TCCR1A;
|
||||
char TCCR1B;
|
||||
char TCCR1C;
|
||||
char TIMSK1;
|
||||
char TIFR1;
|
||||
unsigned short OCR1A;
|
||||
unsigned short OCR1B;
|
||||
|
||||
FastAccelStepper *stepper;
|
||||
StepperQueue fas_queue[NUM_QUEUES];
|
||||
|
||||
int enable_inject_on_mark = -1;
|
||||
bool enable_stepper_manage_on_interrupts = false;
|
||||
bool enable_stepper_manage_on_noInterrupts = false;
|
||||
bool in_manage = false;
|
||||
|
||||
#include "RampChecker.h"
|
||||
class FastAccelStepperTest {
|
||||
public:
|
||||
void init_queue() {
|
||||
fas_queue[0]._initVars();
|
||||
fas_queue[1]._initVars();
|
||||
}
|
||||
void inject() { stepper->fill_queue(); }
|
||||
void do_test() {
|
||||
init_queue();
|
||||
FastAccelStepper s = FastAccelStepper();
|
||||
s.init(NULL, 0, 0);
|
||||
stepper = &s;
|
||||
|
||||
RampChecker rc = RampChecker();
|
||||
assert(0 == s.getCurrentPosition());
|
||||
|
||||
int32_t steps = 10000;
|
||||
|
||||
// Increase speed to 400, then further to 300
|
||||
// Identified bug was a fast jump to 300 without acceleration
|
||||
assert(s.isQueueEmpty());
|
||||
s.setSpeedInUs(400);
|
||||
s.setAcceleration(10000);
|
||||
in_manage = true;
|
||||
s.fill_queue();
|
||||
in_manage = false;
|
||||
assert(s.isQueueEmpty());
|
||||
assert(!s.isRunning());
|
||||
s.moveTo(3000);
|
||||
assert(s.isRunning());
|
||||
in_manage = true;
|
||||
s.fill_queue();
|
||||
in_manage = false;
|
||||
assert(!s.isQueueEmpty());
|
||||
|
||||
float old_planned_time_in_buffer = 0;
|
||||
int moveto_done = false;
|
||||
for (int i = 0; i < steps; i++) {
|
||||
if (!moveto_done && (s.getCurrentPosition() >= 500)) {
|
||||
moveto_done = true;
|
||||
s.moveTo(4000);
|
||||
}
|
||||
if (true) {
|
||||
printf(
|
||||
"Loop %d: Queue read/write = %d/%d Target pos = %d, Queue End "
|
||||
"pos = %d QueueEmpty=%s\n",
|
||||
i, fas_queue[0].read_idx, fas_queue[0].next_write_idx,
|
||||
s.targetPos(), s.getPositionAfterCommandsCompleted(),
|
||||
s.isQueueEmpty() ? "yes" : "no");
|
||||
}
|
||||
in_manage = true;
|
||||
if (!s.isRampGeneratorActive() && s.isQueueEmpty()) {
|
||||
break;
|
||||
}
|
||||
s.fill_queue();
|
||||
uint32_t from_dt = rc.total_ticks;
|
||||
while (!s.isQueueEmpty()) {
|
||||
rc.check_section(
|
||||
&fas_queue[0].entry[fas_queue[0].read_idx & QUEUE_LEN_MASK]);
|
||||
fas_queue[0].read_idx++;
|
||||
}
|
||||
in_manage = false;
|
||||
uint32_t to_dt = rc.total_ticks;
|
||||
float planned_time = (to_dt - from_dt) * 1.0 / 16000000;
|
||||
printf("%d: planned time in buffer: %.6fs\n", i, planned_time);
|
||||
// This must be ensured, so that the stepper does not run out of commands
|
||||
old_planned_time_in_buffer = planned_time;
|
||||
}
|
||||
test(!s.isRampGeneratorActive(), "too many commands created");
|
||||
printf("Total time %f\n", rc.total_ticks / 16000000.0);
|
||||
#if (TEST_CREATE_QUEUE_CHECKSUM == 1)
|
||||
printf("CHECKSUM for %d/%d/%d: %d\n", steps, travel_dt, accel, s.checksum);
|
||||
#endif
|
||||
printf("Total steps = %d\n", rc.pos);
|
||||
assert(rc.pos == 4000);
|
||||
|
||||
printf("TEST_05 Part PASSED\n");
|
||||
}
|
||||
};
|
||||
|
||||
FastAccelStepperTest test;
|
||||
void inject_fill_interrupt(int mark) {
|
||||
if ((mark == enable_inject_on_mark) && !in_manage) {
|
||||
in_manage = true;
|
||||
test.inject();
|
||||
in_manage = false;
|
||||
}
|
||||
}
|
||||
void noInterrupts() {
|
||||
if (enable_stepper_manage_on_noInterrupts && !in_manage) {
|
||||
in_manage = true;
|
||||
test.inject();
|
||||
in_manage = false;
|
||||
}
|
||||
}
|
||||
void interrupts() {
|
||||
if (enable_stepper_manage_on_interrupts && !in_manage) {
|
||||
in_manage = true;
|
||||
test.inject();
|
||||
in_manage = false;
|
||||
}
|
||||
}
|
||||
int main() {
|
||||
enable_stepper_manage_on_interrupts = false;
|
||||
enable_stepper_manage_on_noInterrupts = false;
|
||||
enable_inject_on_mark = -1;
|
||||
test.do_test();
|
||||
|
||||
enable_stepper_manage_on_interrupts = false;
|
||||
enable_stepper_manage_on_noInterrupts = false;
|
||||
enable_inject_on_mark = 0;
|
||||
test.do_test();
|
||||
|
||||
enable_stepper_manage_on_interrupts = false;
|
||||
enable_stepper_manage_on_noInterrupts = false;
|
||||
enable_inject_on_mark = 1;
|
||||
test.do_test();
|
||||
|
||||
enable_stepper_manage_on_interrupts = false;
|
||||
enable_stepper_manage_on_noInterrupts = false;
|
||||
enable_inject_on_mark = 2;
|
||||
test.do_test();
|
||||
|
||||
enable_stepper_manage_on_interrupts = false;
|
||||
enable_stepper_manage_on_noInterrupts = true;
|
||||
enable_inject_on_mark = -1;
|
||||
test.do_test();
|
||||
|
||||
enable_stepper_manage_on_interrupts = true;
|
||||
enable_stepper_manage_on_noInterrupts = false;
|
||||
enable_inject_on_mark = -1;
|
||||
test.do_test();
|
||||
|
||||
printf("TEST_05 PASSED\n");
|
||||
return 0;
|
||||
}
|
||||
189
extras/tests/pc_based/test_06.cpp
Normal file
189
extras/tests/pc_based/test_06.cpp
Normal file
@@ -0,0 +1,189 @@
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "FastAccelStepper.h"
|
||||
#include "StepperISR.h"
|
||||
|
||||
char TCCR1A;
|
||||
char TCCR1B;
|
||||
char TCCR1C;
|
||||
char TIMSK1;
|
||||
char TIFR1;
|
||||
unsigned short OCR1A;
|
||||
unsigned short OCR1B;
|
||||
|
||||
StepperQueue fas_queue[NUM_QUEUES];
|
||||
|
||||
void inject_fill_interrupt(int mark) {}
|
||||
void noInterrupts() {}
|
||||
void interrupts() {}
|
||||
|
||||
#include "RampChecker.h"
|
||||
|
||||
class FastAccelStepperTest {
|
||||
public:
|
||||
void init_queue() {
|
||||
fas_queue[0].read_idx = 0;
|
||||
fas_queue[1].read_idx = 0;
|
||||
fas_queue[0].next_write_idx = 0;
|
||||
fas_queue[1].next_write_idx = 0;
|
||||
}
|
||||
|
||||
void do_test1() {
|
||||
init_queue();
|
||||
FastAccelStepper s = FastAccelStepper();
|
||||
s.init(NULL, 0, 0);
|
||||
RampChecker rc = RampChecker();
|
||||
assert(0 == s.getCurrentPosition());
|
||||
|
||||
int32_t steps = 15000;
|
||||
|
||||
// This sequence caused no stop:
|
||||
// M1 N A100000 V4000 R15000
|
||||
// V4300 U
|
||||
// S
|
||||
|
||||
assert(s.isQueueEmpty());
|
||||
s.setSpeedInUs(4000);
|
||||
s.setAcceleration(100000);
|
||||
s.fill_queue();
|
||||
assert(s.isQueueEmpty());
|
||||
s.move(steps);
|
||||
s.fill_queue();
|
||||
assert(!s.isQueueEmpty());
|
||||
float old_planned_time_in_buffer = 0;
|
||||
bool speed_changed = false;
|
||||
bool stop_initiated = false;
|
||||
for (int i = 0; i < steps; i++) {
|
||||
if (!speed_changed && (s.getCurrentPosition() >= 1000)) {
|
||||
puts("Change speed to 4300us");
|
||||
s.fill_queue(); // ensure queue is not empty
|
||||
speed_changed = true;
|
||||
s.setSpeedInUs(4300);
|
||||
s.applySpeedAcceleration();
|
||||
}
|
||||
if (!stop_initiated && (s.getCurrentPosition() >= 2000)) {
|
||||
puts("Init stop");
|
||||
s.fill_queue(); // ensure queue is not empty
|
||||
stop_initiated = true;
|
||||
s.stopMove();
|
||||
}
|
||||
if (true) {
|
||||
printf(
|
||||
"Loop %d: Queue read/write = %d/%d Target pos = %d, Queue End "
|
||||
"pos = %d QueueEmpty=%s\n",
|
||||
i, fas_queue[0].read_idx, fas_queue[0].next_write_idx,
|
||||
s.targetPos(), s.getPositionAfterCommandsCompleted(),
|
||||
s.isQueueEmpty() ? "yes" : "no");
|
||||
}
|
||||
if (!s.isRampGeneratorActive()) {
|
||||
break;
|
||||
}
|
||||
s.fill_queue();
|
||||
uint32_t from_dt = rc.total_ticks;
|
||||
while (!s.isQueueEmpty()) {
|
||||
rc.check_section(
|
||||
&fas_queue[0].entry[fas_queue[0].read_idx & QUEUE_LEN_MASK]);
|
||||
fas_queue[0].read_idx++;
|
||||
}
|
||||
uint32_t to_dt = rc.total_ticks;
|
||||
float planned_time = (to_dt - from_dt) * 1.0 / 16000000;
|
||||
printf("planned time in buffer: %.6fs\n", planned_time);
|
||||
// This must be ensured, so that the stepper does not run out of commands
|
||||
assert((i == 0) || (old_planned_time_in_buffer > 0.005));
|
||||
old_planned_time_in_buffer = planned_time;
|
||||
}
|
||||
test(!s.isRampGeneratorActive(), "too many commands created");
|
||||
test(s.getCurrentPosition() != steps, "has not stopped");
|
||||
printf("Total time %f\n", rc.total_ticks / 16000000.0);
|
||||
#if (TEST_CREATE_QUEUE_CHECKSUM == 1)
|
||||
printf("CHECKSUM for %d/%d/%d: %d\n", steps, travel_dt, accel, s.checksum);
|
||||
#endif
|
||||
}
|
||||
|
||||
void do_test2(uint32_t stop_at_position) {
|
||||
printf("do_test2 with stop at %d\n", stop_at_position);
|
||||
init_queue();
|
||||
FastAccelStepper s = FastAccelStepper();
|
||||
s.init(NULL, 0, 0);
|
||||
RampChecker rc = RampChecker();
|
||||
assert(0 == s.getCurrentPosition());
|
||||
|
||||
int32_t steps = 15000;
|
||||
|
||||
// This sequence does not run to position 9999:
|
||||
// M1 N A100 V100 P9999 w100 S W P9999
|
||||
|
||||
assert(s.isQueueEmpty());
|
||||
s.setSpeedInUs(100);
|
||||
s.setAcceleration(100);
|
||||
s.fill_queue();
|
||||
assert(s.isQueueEmpty());
|
||||
s.moveTo(9999);
|
||||
s.fill_queue();
|
||||
assert(!s.isQueueEmpty());
|
||||
float old_planned_time_in_buffer = 0;
|
||||
bool stop_initiated = false;
|
||||
bool restarted = false;
|
||||
for (int i = 0; i < steps; i++) {
|
||||
if (!stop_initiated && (s.getCurrentPosition() >= stop_at_position)) {
|
||||
puts("Init stop");
|
||||
s.fill_queue(); // ensure queue is not empty
|
||||
stop_initiated = true;
|
||||
s.stopMove();
|
||||
}
|
||||
if (true) {
|
||||
printf(
|
||||
"Loop %d: Queue read/write = %d/%d Target pos = %d, Queue End "
|
||||
"pos = %d QueueEmpty=%s\n",
|
||||
i, fas_queue[0].read_idx, fas_queue[0].next_write_idx,
|
||||
s.targetPos(), s.getPositionAfterCommandsCompleted(),
|
||||
s.isQueueEmpty() ? "yes" : "no");
|
||||
}
|
||||
s.fill_queue();
|
||||
uint32_t from_dt = rc.total_ticks;
|
||||
if (!s.isQueueEmpty()) {
|
||||
while (!s.isQueueEmpty()) {
|
||||
rc.check_section(
|
||||
&fas_queue[0].entry[fas_queue[0].read_idx & QUEUE_LEN_MASK]);
|
||||
fas_queue[0].read_idx++;
|
||||
}
|
||||
uint32_t to_dt = rc.total_ticks;
|
||||
float planned_time = (to_dt - from_dt) * 1.0 / 16000000;
|
||||
printf("planned time in buffer: %.6fs\n", planned_time);
|
||||
// This must be ensured, so that the stepper does not run out of
|
||||
// commands
|
||||
assert((i == 0) || (old_planned_time_in_buffer > 0.005));
|
||||
old_planned_time_in_buffer = planned_time;
|
||||
}
|
||||
if (!s.isRampGeneratorActive()) {
|
||||
if (restarted) {
|
||||
break;
|
||||
}
|
||||
puts("Continue move to end position");
|
||||
rc.next_ramp();
|
||||
restarted = true;
|
||||
s.moveTo(9999);
|
||||
}
|
||||
}
|
||||
printf("do_test2 with stop at %d\n", stop_at_position);
|
||||
test(!s.isRampGeneratorActive(), "too many commands created");
|
||||
printf("getCurrentPosition() = %d\n", s.getCurrentPosition());
|
||||
test(s.getCurrentPosition() == 9999, "has not reached end position");
|
||||
printf("Total time %f\n", rc.total_ticks / 16000000.0);
|
||||
#if (TEST_CREATE_QUEUE_CHECKSUM == 1)
|
||||
printf("CHECKSUM for %d/%d/%d: %d\n", steps, travel_dt, accel, s.checksum);
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
int main() {
|
||||
FastAccelStepperTest test;
|
||||
test.do_test1();
|
||||
test.do_test2(100);
|
||||
test.do_test2(5000);
|
||||
test.do_test2(9000);
|
||||
printf("TEST_06 PASSED\n");
|
||||
return 0;
|
||||
}
|
||||
132
extras/tests/pc_based/test_07.cpp
Normal file
132
extras/tests/pc_based/test_07.cpp
Normal file
@@ -0,0 +1,132 @@
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <cinttypes>
|
||||
|
||||
#include "FastAccelStepper.h"
|
||||
#include "StepperISR.h"
|
||||
|
||||
char TCCR1A;
|
||||
char TCCR1B;
|
||||
char TCCR1C;
|
||||
char TIMSK1;
|
||||
char TIFR1;
|
||||
unsigned short OCR1A;
|
||||
unsigned short OCR1B;
|
||||
|
||||
StepperQueue fas_queue[NUM_QUEUES];
|
||||
|
||||
void inject_fill_interrupt(int mark) {}
|
||||
void noInterrupts() {}
|
||||
void interrupts() {}
|
||||
|
||||
#include "RampChecker.h"
|
||||
|
||||
class FastAccelStepperTest {
|
||||
public:
|
||||
void init_queue() {
|
||||
fas_queue[0].read_idx = 0;
|
||||
fas_queue[1].read_idx = 0;
|
||||
fas_queue[0].next_write_idx = 0;
|
||||
fas_queue[1].next_write_idx = 0;
|
||||
}
|
||||
|
||||
void do_test(uint64_t dt) {
|
||||
init_queue();
|
||||
FastAccelStepper s = FastAccelStepper();
|
||||
s.init(NULL, 0, 0);
|
||||
RampChecker rc = RampChecker();
|
||||
assert(0 == s.getCurrentPosition());
|
||||
|
||||
// Reproduce test sequence 06
|
||||
|
||||
assert(s.getDirectionPin() == PIN_UNDEFINED);
|
||||
uint32_t speed_us = 100;
|
||||
int32_t steps = 32000;
|
||||
assert(s.isQueueEmpty());
|
||||
s.setSpeedInUs(speed_us);
|
||||
s.setAcceleration(10000);
|
||||
s.fill_queue();
|
||||
assert(s.isQueueEmpty());
|
||||
s.move(steps);
|
||||
s.fill_queue();
|
||||
assert(!s.isQueueEmpty());
|
||||
float old_planned_time_in_buffer = 0;
|
||||
uint64_t next_speed_change = dt;
|
||||
uint64_t mid_point_ticks = 0;
|
||||
|
||||
char fname[100];
|
||||
snprintf(fname, 100, "test_07.gnuplot");
|
||||
rc.start_plot(fname);
|
||||
for (int i = 0; i < 10 * steps; i++) {
|
||||
if (rc.total_ticks > next_speed_change) {
|
||||
next_speed_change += TICKS_PER_S / 10;
|
||||
speed_us = 190 - speed_us;
|
||||
printf("Change speed to %d\n", speed_us);
|
||||
s.setSpeedInUs(speed_us);
|
||||
s.applySpeedAcceleration();
|
||||
}
|
||||
if (true) {
|
||||
printf(
|
||||
"Loop %d: Queue read/write = %d/%d Target pos = %d, Queue End "
|
||||
"pos = %d QueueEmpty=%s\n",
|
||||
i, fas_queue[0].read_idx, fas_queue[0].next_write_idx,
|
||||
s.targetPos(), s.getPositionAfterCommandsCompleted(),
|
||||
s.isQueueEmpty() ? "yes" : "no");
|
||||
}
|
||||
if (!s.isRampGeneratorActive()) {
|
||||
break;
|
||||
}
|
||||
s.fill_queue();
|
||||
uint32_t from_dt = rc.total_ticks;
|
||||
while (!s.isQueueEmpty()) {
|
||||
if ((mid_point_ticks == 0) && (rc.pos >= steps / 2)) {
|
||||
mid_point_ticks = rc.total_ticks;
|
||||
}
|
||||
rc.increase_ok = true;
|
||||
rc.decrease_ok = true;
|
||||
rc.check_section(
|
||||
&fas_queue[0].entry[fas_queue[0].read_idx & QUEUE_LEN_MASK]);
|
||||
fas_queue[0].read_idx++;
|
||||
}
|
||||
uint32_t to_dt = rc.total_ticks;
|
||||
float planned_time = (to_dt - from_dt) * 1.0 / 16000000;
|
||||
printf("planned time in buffer: %.6fs\n", planned_time);
|
||||
// This must be ensured, so that the stepper does not run out of commands
|
||||
assert((i == 0) || (old_planned_time_in_buffer > 0.005));
|
||||
old_planned_time_in_buffer = planned_time;
|
||||
test(s.getCurrentPosition() <= steps, "has overshot");
|
||||
}
|
||||
rc.finish_plot();
|
||||
test(!s.isRampGeneratorActive(), "too many commands created");
|
||||
test(s.getCurrentPosition() == steps, "has not reached target position");
|
||||
printf("Total time %f\n", rc.total_ticks / 16000000.0);
|
||||
|
||||
printf("Time coasting = %d\n", rc.time_coasting);
|
||||
test(rc.time_coasting < 46000000, "too much coasting");
|
||||
|
||||
printf("mid point @ %" PRIu64 " => total = %" PRIu64
|
||||
", total ticks = %" PRIu64 "\n",
|
||||
mid_point_ticks, 2 * mid_point_ticks, rc.total_ticks);
|
||||
#define ALLOWED_ASYMMETRY 1000000L
|
||||
printf("%ld\n", ALLOWED_ASYMMETRY);
|
||||
test(mid_point_ticks * 2 < rc.total_ticks + ALLOWED_ASYMMETRY,
|
||||
"ramp is not symmetric 1");
|
||||
test(mid_point_ticks * 2 > rc.total_ticks - ALLOWED_ASYMMETRY,
|
||||
"ramp is not symmetric 2");
|
||||
|
||||
#if (TEST_CREATE_QUEUE_CHECKSUM == 1)
|
||||
printf("CHECKSUM for %d/%d/%d: %d\n", steps, travel_dt, accel, s.checksum);
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
int main() {
|
||||
FastAccelStepperTest test;
|
||||
for (uint64_t time_shift = 0; time_shift < TICKS_PER_S / 10;
|
||||
time_shift += TICKS_PER_S / 7000) {
|
||||
test.do_test(time_shift);
|
||||
}
|
||||
printf("TEST_07 PASSED\n");
|
||||
return 0;
|
||||
}
|
||||
103
extras/tests/pc_based/test_08.cpp
Normal file
103
extras/tests/pc_based/test_08.cpp
Normal file
@@ -0,0 +1,103 @@
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "FastAccelStepper.h"
|
||||
#include "StepperISR.h"
|
||||
|
||||
char TCCR1A;
|
||||
char TCCR1B;
|
||||
char TCCR1C;
|
||||
char TIMSK1;
|
||||
char TIFR1;
|
||||
unsigned short OCR1A;
|
||||
unsigned short OCR1B;
|
||||
|
||||
StepperQueue fas_queue[NUM_QUEUES];
|
||||
|
||||
void inject_fill_interrupt(int mark) {}
|
||||
void noInterrupts() {}
|
||||
void interrupts() {}
|
||||
|
||||
#include "RampChecker.h"
|
||||
|
||||
class FastAccelStepperTest {
|
||||
public:
|
||||
void init_queue() {
|
||||
fas_queue[0].read_idx = 0;
|
||||
fas_queue[1].read_idx = 0;
|
||||
fas_queue[0].next_write_idx = 0;
|
||||
fas_queue[1].next_write_idx = 0;
|
||||
}
|
||||
|
||||
void ramp(uint32_t accel, uint32_t steps) {
|
||||
init_queue();
|
||||
FastAccelStepper s = FastAccelStepper();
|
||||
s.init(NULL, 0, 0);
|
||||
RampChecker rc = RampChecker();
|
||||
assert(0 == s.getCurrentPosition());
|
||||
|
||||
// Reproduce test sequence 06
|
||||
|
||||
uint32_t speed_us = 40;
|
||||
assert(s.isQueueEmpty());
|
||||
s.setSpeedInUs(speed_us);
|
||||
s.setAcceleration(accel);
|
||||
s.fill_queue();
|
||||
assert(s.isQueueEmpty());
|
||||
s.move(steps);
|
||||
s.fill_queue();
|
||||
assert(!s.isQueueEmpty());
|
||||
float old_planned_time_in_buffer = 0;
|
||||
|
||||
char fname[100];
|
||||
snprintf(fname, 100, "test_08.gnuplot");
|
||||
rc.start_plot(fname);
|
||||
for (int i = 0; i < 100 * steps; i++) {
|
||||
if (true) {
|
||||
printf(
|
||||
"Loop %d: Queue read/write = %d/%d Target pos = %d, Queue End "
|
||||
"pos = %d QueueEmpty=%s\n",
|
||||
i, fas_queue[0].read_idx, fas_queue[0].next_write_idx,
|
||||
s.targetPos(), s.getPositionAfterCommandsCompleted(),
|
||||
s.isQueueEmpty() ? "yes" : "no");
|
||||
}
|
||||
if (!s.isRampGeneratorActive()) {
|
||||
break;
|
||||
}
|
||||
s.fill_queue();
|
||||
uint32_t from_dt = rc.total_ticks;
|
||||
while (!s.isQueueEmpty()) {
|
||||
rc.increase_ok = true;
|
||||
rc.decrease_ok = true;
|
||||
rc.check_section(
|
||||
&fas_queue[0].entry[fas_queue[0].read_idx & QUEUE_LEN_MASK]);
|
||||
fas_queue[0].read_idx++;
|
||||
}
|
||||
uint32_t to_dt = rc.total_ticks;
|
||||
float planned_time = (to_dt - from_dt) * 1.0 / 16000000;
|
||||
printf("planned time in buffer: %.6fs\n", planned_time);
|
||||
// This must be ensured, so that the stepper does not run out of commands
|
||||
assert((i == 0) || (old_planned_time_in_buffer > 0.005));
|
||||
old_planned_time_in_buffer = planned_time;
|
||||
}
|
||||
rc.finish_plot();
|
||||
test(!s.isRampGeneratorActive(), "too many commands created");
|
||||
test(s.getCurrentPosition() == steps, "has not reached target position");
|
||||
printf("Total time %f\n", rc.total_ticks / 16000000.0);
|
||||
|
||||
#if (TEST_CREATE_QUEUE_CHECKSUM == 1)
|
||||
printf("CHECKSUM for %d/%d/%d: %d\n", steps, travel_dt, accel, s.checksum);
|
||||
#endif
|
||||
}
|
||||
};
|
||||
int main() {
|
||||
FastAccelStepperTest test;
|
||||
test.ramp(100000, 400);
|
||||
test.ramp(100000, 600);
|
||||
for (uint32_t i = 0; i < 30; i++) {
|
||||
test.ramp(1000000, 1000 + i);
|
||||
}
|
||||
printf("TEST_08 PASSED\n");
|
||||
return 0;
|
||||
}
|
||||
99
extras/tests/pc_based/test_09.cpp
Normal file
99
extras/tests/pc_based/test_09.cpp
Normal file
@@ -0,0 +1,99 @@
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "FastAccelStepper.h"
|
||||
#include "StepperISR.h"
|
||||
|
||||
char TCCR1A;
|
||||
char TCCR1B;
|
||||
char TCCR1C;
|
||||
char TIMSK1;
|
||||
char TIFR1;
|
||||
unsigned short OCR1A;
|
||||
unsigned short OCR1B;
|
||||
|
||||
StepperQueue fas_queue[NUM_QUEUES];
|
||||
|
||||
void inject_fill_interrupt(int mark) {}
|
||||
void noInterrupts() {}
|
||||
void interrupts() {}
|
||||
|
||||
#include "RampChecker.h"
|
||||
|
||||
class FastAccelStepperTest {
|
||||
public:
|
||||
void init_queue() {
|
||||
fas_queue[0].read_idx = 0;
|
||||
fas_queue[1].read_idx = 0;
|
||||
fas_queue[0].next_write_idx = 0;
|
||||
fas_queue[1].next_write_idx = 0;
|
||||
}
|
||||
|
||||
void ramp(uint32_t steps) {
|
||||
init_queue();
|
||||
FastAccelStepper s = FastAccelStepper();
|
||||
s.init(NULL, 0, 0);
|
||||
RampChecker rc = RampChecker();
|
||||
assert(0 == s.getCurrentPosition());
|
||||
|
||||
uint32_t speed_us = 40;
|
||||
assert(s.isQueueEmpty());
|
||||
s.setSpeedInUs(speed_us);
|
||||
s.setAcceleration(1000000);
|
||||
s.fill_queue();
|
||||
assert(s.isQueueEmpty());
|
||||
float old_planned_time_in_buffer = 0;
|
||||
|
||||
char fname[100];
|
||||
snprintf(fname, 100, "test_09.gnuplot");
|
||||
rc.start_plot(fname);
|
||||
for (int j = 0; j < 2; j++) {
|
||||
s.move(steps);
|
||||
for (int i = 0; i < 100 * steps; i++) {
|
||||
if (true) {
|
||||
printf(
|
||||
"Loop %d: Queue read/write = %d/%d Target pos = %d, Queue End "
|
||||
"pos = %d QueueEmpty=%s\n",
|
||||
i, fas_queue[0].read_idx, fas_queue[0].next_write_idx,
|
||||
s.targetPos(), s.getPositionAfterCommandsCompleted(),
|
||||
s.isQueueEmpty() ? "yes" : "no");
|
||||
}
|
||||
if (!s.isRampGeneratorActive()) {
|
||||
break;
|
||||
}
|
||||
s.fill_queue();
|
||||
uint32_t from_dt = rc.total_ticks;
|
||||
while (!s.isQueueEmpty()) {
|
||||
rc.increase_ok = true;
|
||||
rc.decrease_ok = true;
|
||||
rc.check_section(
|
||||
&fas_queue[0].entry[fas_queue[0].read_idx & QUEUE_LEN_MASK]);
|
||||
fas_queue[0].read_idx++;
|
||||
}
|
||||
uint32_t to_dt = rc.total_ticks;
|
||||
float planned_time = (to_dt - from_dt) * 1.0 / 16000000;
|
||||
printf("planned time in buffer: %.6fs\n", planned_time);
|
||||
// This must be ensured, so that the stepper does not run out of
|
||||
// commands
|
||||
assert((i == 0) || (old_planned_time_in_buffer > 0.005));
|
||||
old_planned_time_in_buffer = planned_time;
|
||||
}
|
||||
}
|
||||
rc.finish_plot();
|
||||
test(!s.isRampGeneratorActive(), "too many commands created");
|
||||
test(s.getCurrentPosition() == 2 * steps,
|
||||
"has not reached target position");
|
||||
printf("Total time %f\n", rc.total_ticks / 16000000.0);
|
||||
|
||||
#if (TEST_CREATE_QUEUE_CHECKSUM == 1)
|
||||
printf("CHECKSUM for %d/%d/%d: %d\n", steps, travel_dt, accel, s.checksum);
|
||||
#endif
|
||||
}
|
||||
};
|
||||
int main() {
|
||||
FastAccelStepperTest test;
|
||||
test.ramp(53);
|
||||
printf("TEST_09 PASSED\n");
|
||||
return 0;
|
||||
}
|
||||
107
extras/tests/pc_based/test_10.cpp
Normal file
107
extras/tests/pc_based/test_10.cpp
Normal file
@@ -0,0 +1,107 @@
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "FastAccelStepper.h"
|
||||
#include "StepperISR.h"
|
||||
|
||||
char TCCR1A;
|
||||
char TCCR1B;
|
||||
char TCCR1C;
|
||||
char TIMSK1;
|
||||
char TIFR1;
|
||||
unsigned short OCR1A;
|
||||
unsigned short OCR1B;
|
||||
|
||||
StepperQueue fas_queue[NUM_QUEUES];
|
||||
|
||||
void inject_fill_interrupt(int mark) {}
|
||||
void noInterrupts() {}
|
||||
void interrupts() {}
|
||||
|
||||
#include "RampChecker.h"
|
||||
|
||||
class FastAccelStepperTest {
|
||||
public:
|
||||
void init_queue() {
|
||||
fas_queue[0].read_idx = 0;
|
||||
fas_queue[1].read_idx = 0;
|
||||
fas_queue[0].next_write_idx = 0;
|
||||
fas_queue[1].next_write_idx = 0;
|
||||
}
|
||||
|
||||
void reduce_acceleration() {
|
||||
puts("Test test_speed_decrease");
|
||||
init_queue();
|
||||
FastAccelStepper s = FastAccelStepper();
|
||||
s.init(NULL, 0, 0);
|
||||
RampChecker rc = RampChecker();
|
||||
assert(0 == s.getCurrentPosition());
|
||||
|
||||
int32_t steps = 100000;
|
||||
|
||||
// Increase speed to 400, then further to 300
|
||||
// Identified bug was a fast jump to 300 without acceleration
|
||||
assert(s.isQueueEmpty());
|
||||
s.setSpeedInUs(30);
|
||||
s.fill_queue();
|
||||
assert(s.isQueueEmpty());
|
||||
s.moveByAcceleration(17164);
|
||||
s.fill_queue();
|
||||
assert(!s.isQueueEmpty());
|
||||
float old_planned_time_in_buffer = 0;
|
||||
int accel_decreased = false;
|
||||
uint32_t count_state_dec = 0;
|
||||
for (int i = 0; i < steps * 10; i++) {
|
||||
if (!accel_decreased && (s.getCurrentPosition() >= 35000)) {
|
||||
puts("Change acceleration");
|
||||
accel_decreased = true;
|
||||
s.moveByAcceleration(-1000);
|
||||
s.fill_queue(); // ensure queue is not empty
|
||||
}
|
||||
if (accel_decreased && (s.getCurrentPosition() >= 37000)) {
|
||||
test((s.rampState() & RAMP_STATE_MASK) != RAMP_STATE_COAST,
|
||||
"Coasting is wrong state here");
|
||||
break;
|
||||
}
|
||||
if (true) {
|
||||
printf(
|
||||
"Loop %d: Queue read/write = %d/%d Target pos = %d, Queue End "
|
||||
"pos = %d QueueEmpty=%s\n",
|
||||
i, fas_queue[0].read_idx, fas_queue[0].next_write_idx,
|
||||
s.targetPos(), s.getPositionAfterCommandsCompleted(),
|
||||
s.isQueueEmpty() ? "yes" : "no");
|
||||
}
|
||||
if (!s.isRampGeneratorActive()) {
|
||||
break;
|
||||
}
|
||||
s.fill_queue();
|
||||
if ((s.rampState() & RAMP_STATE_MASK) == RAMP_STATE_DECELERATE) {
|
||||
count_state_dec++;
|
||||
}
|
||||
uint32_t from_dt = rc.total_ticks;
|
||||
while (!s.isQueueEmpty()) {
|
||||
rc.check_section(
|
||||
&fas_queue[0].entry[fas_queue[0].read_idx & QUEUE_LEN_MASK]);
|
||||
fas_queue[0].read_idx++;
|
||||
}
|
||||
uint32_t to_dt = rc.total_ticks;
|
||||
float planned_time = (to_dt - from_dt) * 1.0 / 16000000;
|
||||
printf("planned time in buffer: %.6fs\n", planned_time);
|
||||
// This must be ensured, so that the stepper does not run out of commands
|
||||
assert((i == 0) || (old_planned_time_in_buffer > 0.005));
|
||||
old_planned_time_in_buffer = planned_time;
|
||||
}
|
||||
printf("Total time %f\n", rc.total_ticks / 16000000.0);
|
||||
#if (TEST_CREATE_QUEUE_CHECKSUM == 1)
|
||||
printf("CHECKSUM for %d/%d/%d: %d\n", steps, travel_dt, accel, s.checksum);
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
int main() {
|
||||
FastAccelStepperTest test;
|
||||
test.reduce_acceleration();
|
||||
printf("TEST_10 PASSED\n");
|
||||
return 0;
|
||||
}
|
||||
108
extras/tests/pc_based/test_11.cpp
Normal file
108
extras/tests/pc_based/test_11.cpp
Normal file
@@ -0,0 +1,108 @@
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "FastAccelStepper.h"
|
||||
#include "StepperISR.h"
|
||||
|
||||
char TCCR1A;
|
||||
char TCCR1B;
|
||||
char TCCR1C;
|
||||
char TIMSK1;
|
||||
char TIFR1;
|
||||
unsigned short OCR1A;
|
||||
unsigned short OCR1B;
|
||||
|
||||
StepperQueue fas_queue[NUM_QUEUES];
|
||||
|
||||
void inject_fill_interrupt(int mark) {}
|
||||
void noInterrupts() {}
|
||||
void interrupts() {}
|
||||
|
||||
#include "RampChecker.h"
|
||||
|
||||
class FastAccelStepperTest {
|
||||
public:
|
||||
void init_queue() {
|
||||
fas_queue[0].read_idx = 0;
|
||||
fas_queue[1].read_idx = 0;
|
||||
fas_queue[0].next_write_idx = 0;
|
||||
fas_queue[1].next_write_idx = 0;
|
||||
}
|
||||
|
||||
void reduce_speed() {
|
||||
puts("Test test_speed_decrease");
|
||||
init_queue();
|
||||
FastAccelStepper s = FastAccelStepper();
|
||||
s.init(NULL, 0, 0);
|
||||
RampChecker rc = RampChecker();
|
||||
assert(0 == s.getCurrentPosition());
|
||||
|
||||
int32_t steps = 100;
|
||||
|
||||
// M1 A1000 V10000 P100 w300 V100000 U
|
||||
assert(s.isQueueEmpty());
|
||||
s.setAcceleration(1000);
|
||||
s.setSpeedInUs(10000);
|
||||
s.fill_queue();
|
||||
assert(s.isQueueEmpty());
|
||||
s.moveTo(100);
|
||||
s.fill_queue();
|
||||
assert(!s.isQueueEmpty());
|
||||
float old_planned_time_in_buffer = 0;
|
||||
int speed_decreased = false;
|
||||
uint32_t count_state_dec = 0;
|
||||
for (int i = 0; i < steps * 10; i++) {
|
||||
if (!speed_decreased && (s.getCurrentPosition() >= 35)) {
|
||||
puts("Change speed");
|
||||
speed_decreased = true;
|
||||
s.setSpeedInUs(100000);
|
||||
s.applySpeedAcceleration();
|
||||
s.fill_queue(); // ensure queue is not empty
|
||||
}
|
||||
if (speed_decreased && (s.getCurrentPosition() >= 90)) {
|
||||
test((s.rampState() & RAMP_STATE_MASK) == RAMP_STATE_COAST,
|
||||
"Coasting is required state here");
|
||||
break;
|
||||
}
|
||||
if (true) {
|
||||
printf(
|
||||
"Loop %d: Queue read/write = %d/%d Target pos = %d, Queue End "
|
||||
"pos = %d QueueEmpty=%s\n",
|
||||
i, fas_queue[0].read_idx, fas_queue[0].next_write_idx,
|
||||
s.targetPos(), s.getPositionAfterCommandsCompleted(),
|
||||
s.isQueueEmpty() ? "yes" : "no");
|
||||
}
|
||||
if (!s.isRampGeneratorActive()) {
|
||||
break;
|
||||
}
|
||||
s.fill_queue();
|
||||
if ((s.rampState() & RAMP_STATE_MASK) == RAMP_STATE_DECELERATE) {
|
||||
count_state_dec++;
|
||||
}
|
||||
uint32_t from_dt = rc.total_ticks;
|
||||
while (!s.isQueueEmpty()) {
|
||||
rc.check_section(
|
||||
&fas_queue[0].entry[fas_queue[0].read_idx & QUEUE_LEN_MASK]);
|
||||
fas_queue[0].read_idx++;
|
||||
}
|
||||
uint32_t to_dt = rc.total_ticks;
|
||||
float planned_time = (to_dt - from_dt) * 1.0 / 16000000;
|
||||
printf("planned time in buffer: %.6fs\n", planned_time);
|
||||
// This must be ensured, so that the stepper does not run out of commands
|
||||
assert((i == 0) || (old_planned_time_in_buffer > 0.005));
|
||||
old_planned_time_in_buffer = planned_time;
|
||||
}
|
||||
printf("Total time %f\n", rc.total_ticks / 16000000.0);
|
||||
#if (TEST_CREATE_QUEUE_CHECKSUM == 1)
|
||||
printf("CHECKSUM for %d/%d/%d: %d\n", steps, travel_dt, accel, s.checksum);
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
int main() {
|
||||
FastAccelStepperTest test;
|
||||
test.reduce_speed();
|
||||
printf("TEST_11 PASSED\n");
|
||||
return 0;
|
||||
}
|
||||
103
extras/tests/pc_based/test_12.cpp
Normal file
103
extras/tests/pc_based/test_12.cpp
Normal file
@@ -0,0 +1,103 @@
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "FastAccelStepper.h"
|
||||
#include "StepperISR.h"
|
||||
|
||||
char TCCR1A;
|
||||
char TCCR1B;
|
||||
char TCCR1C;
|
||||
char TIMSK1;
|
||||
char TIFR1;
|
||||
unsigned short OCR1A;
|
||||
unsigned short OCR1B;
|
||||
|
||||
StepperQueue fas_queue[NUM_QUEUES];
|
||||
|
||||
void inject_fill_interrupt(int mark) {}
|
||||
void noInterrupts() {}
|
||||
void interrupts() {}
|
||||
|
||||
#include "RampChecker.h"
|
||||
|
||||
class FastAccelStepperTest {
|
||||
public:
|
||||
void init_queue() {
|
||||
fas_queue[0].read_idx = 0;
|
||||
fas_queue[1].read_idx = 0;
|
||||
fas_queue[0].next_write_idx = 0;
|
||||
fas_queue[1].next_write_idx = 0;
|
||||
}
|
||||
|
||||
void ramp(uint32_t accel, uint32_t speed_us, uint32_t steps,
|
||||
bool reach_coasting) {
|
||||
init_queue();
|
||||
FastAccelStepper s = FastAccelStepper();
|
||||
s.init(NULL, 0, 0);
|
||||
RampChecker rc = RampChecker();
|
||||
assert(0 == s.getCurrentPosition());
|
||||
|
||||
assert(s.isQueueEmpty());
|
||||
s.setSpeedInUs(speed_us);
|
||||
s.setAcceleration(accel);
|
||||
s.fill_queue();
|
||||
assert(s.isQueueEmpty());
|
||||
s.move(steps);
|
||||
s.fill_queue();
|
||||
assert(!s.isQueueEmpty());
|
||||
float old_planned_time_in_buffer = 0;
|
||||
|
||||
char fname[100];
|
||||
snprintf(fname, 100, "test_12.gnuplot");
|
||||
rc.start_plot(fname);
|
||||
bool coast = false;
|
||||
for (int i = 0; i < 100 * steps; i++) {
|
||||
if (true) {
|
||||
printf(
|
||||
"Loop %d: Queue read/write = %d/%d Target pos = %d, Queue End "
|
||||
"pos = %d QueueEmpty=%s\n",
|
||||
i, fas_queue[0].read_idx, fas_queue[0].next_write_idx,
|
||||
s.targetPos(), s.getPositionAfterCommandsCompleted(),
|
||||
s.isQueueEmpty() ? "yes" : "no");
|
||||
}
|
||||
if (!s.isRampGeneratorActive()) {
|
||||
break;
|
||||
}
|
||||
s.fill_queue();
|
||||
uint32_t from_dt = rc.total_ticks;
|
||||
while (!s.isQueueEmpty()) {
|
||||
rc.increase_ok = true;
|
||||
rc.decrease_ok = true;
|
||||
rc.check_section(
|
||||
&fas_queue[0].entry[fas_queue[0].read_idx & QUEUE_LEN_MASK]);
|
||||
fas_queue[0].read_idx++;
|
||||
}
|
||||
if ((s.rampState() & RAMP_STATE_MASK) == RAMP_STATE_COAST) {
|
||||
coast = true;
|
||||
}
|
||||
uint32_t to_dt = rc.total_ticks;
|
||||
float planned_time = (to_dt - from_dt) * 1.0 / 16000000;
|
||||
printf("planned time in buffer: %.6fs\n", planned_time);
|
||||
// This must be ensured, so that the stepper does not run out of commands
|
||||
assert((i == 0) || (old_planned_time_in_buffer > 0.005));
|
||||
old_planned_time_in_buffer = planned_time;
|
||||
}
|
||||
rc.finish_plot();
|
||||
test(!s.isRampGeneratorActive(), "too many commands created");
|
||||
test(s.getCurrentPosition() == steps, "has not reached target position");
|
||||
test(coast == reach_coasting, "coasting target not met");
|
||||
printf("Total time %f\n", rc.total_ticks / 16000000.0);
|
||||
|
||||
#if (TEST_CREATE_QUEUE_CHECKSUM == 1)
|
||||
printf("CHECKSUM for %d/%d/%d: %d\n", steps, travel_dt, accel, s.checksum);
|
||||
#endif
|
||||
}
|
||||
};
|
||||
int main() {
|
||||
FastAccelStepperTest test;
|
||||
test.ramp(1, 1000, 999000, false);
|
||||
test.ramp(1, 1000, 1001000, true);
|
||||
printf("TEST_12 PASSED\n");
|
||||
return 0;
|
||||
}
|
||||
113
extras/tests/pc_based/test_13.cpp
Normal file
113
extras/tests/pc_based/test_13.cpp
Normal file
@@ -0,0 +1,113 @@
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "FastAccelStepper.h"
|
||||
#include "StepperISR.h"
|
||||
|
||||
char TCCR1A;
|
||||
char TCCR1B;
|
||||
char TCCR1C;
|
||||
char TIMSK1;
|
||||
char TIFR1;
|
||||
unsigned short OCR1A;
|
||||
unsigned short OCR1B;
|
||||
|
||||
StepperQueue fas_queue[NUM_QUEUES];
|
||||
|
||||
void inject_fill_interrupt(int mark) {}
|
||||
void noInterrupts() {}
|
||||
void interrupts() {}
|
||||
|
||||
#include "RampChecker.h"
|
||||
|
||||
class FastAccelStepperTest {
|
||||
public:
|
||||
void init_queue() {
|
||||
fas_queue[0].read_idx = 0;
|
||||
fas_queue[1].read_idx = 0;
|
||||
fas_queue[0].next_write_idx = 0;
|
||||
fas_queue[1].next_write_idx = 0;
|
||||
}
|
||||
|
||||
void ramp(uint32_t accel, uint32_t speed_us, uint32_t steps,
|
||||
bool reach_coasting) {
|
||||
init_queue();
|
||||
FastAccelStepper s = FastAccelStepper();
|
||||
s.init(NULL, 0, 0);
|
||||
RampChecker rc = RampChecker();
|
||||
assert(0 == s.getCurrentPosition());
|
||||
|
||||
assert(s.isQueueEmpty());
|
||||
s.setSpeedInUs(speed_us);
|
||||
s.setAcceleration(accel);
|
||||
s.fill_queue();
|
||||
assert(s.isQueueEmpty());
|
||||
s.move(steps);
|
||||
s.fill_queue();
|
||||
assert(!s.isQueueEmpty());
|
||||
float old_planned_time_in_buffer = 0;
|
||||
|
||||
char fname[100];
|
||||
snprintf(fname, 100, "test_13.gnuplot");
|
||||
rc.start_plot(fname);
|
||||
bool coast = false;
|
||||
for (int i = 0; i < 100 * steps; i++) {
|
||||
if (true) {
|
||||
printf(
|
||||
"Loop %d: Queue read/write = %d/%d Target pos = %d, Queue End "
|
||||
"pos = %d QueueEmpty=%s\n",
|
||||
i, fas_queue[0].read_idx, fas_queue[0].next_write_idx,
|
||||
s.targetPos(), s.getPositionAfterCommandsCompleted(),
|
||||
s.isQueueEmpty() ? "yes" : "no");
|
||||
}
|
||||
if (!s.isRampGeneratorActive()) {
|
||||
break;
|
||||
}
|
||||
s.fill_queue();
|
||||
uint32_t from_dt = rc.total_ticks;
|
||||
while (!s.isQueueEmpty()) {
|
||||
rc.increase_ok = true;
|
||||
rc.decrease_ok = true;
|
||||
rc.check_section(
|
||||
&fas_queue[0].entry[fas_queue[0].read_idx & QUEUE_LEN_MASK]);
|
||||
fas_queue[0].read_idx++;
|
||||
}
|
||||
if ((s.rampState() & RAMP_STATE_MASK) == RAMP_STATE_COAST) {
|
||||
coast = true;
|
||||
}
|
||||
uint32_t to_dt = rc.total_ticks;
|
||||
float planned_time = (to_dt - from_dt) * 1.0 / 16000000;
|
||||
printf("planned time in buffer: %.6fs\n", planned_time);
|
||||
// This must be ensured, so that the stepper does not run out of commands
|
||||
assert((i == 0) || (old_planned_time_in_buffer > 0.005));
|
||||
old_planned_time_in_buffer = planned_time;
|
||||
}
|
||||
while (!s.isQueueEmpty()) {
|
||||
rc.increase_ok = true;
|
||||
rc.decrease_ok = true;
|
||||
rc.check_section(
|
||||
&fas_queue[0].entry[fas_queue[0].read_idx & QUEUE_LEN_MASK]);
|
||||
fas_queue[0].read_idx++;
|
||||
}
|
||||
rc.finish_plot();
|
||||
test(!s.isRampGeneratorActive(), "too many commands created");
|
||||
test(s.getCurrentPosition() == steps, "has not reached target position");
|
||||
test(coast == reach_coasting, "coasting target not met");
|
||||
printf("Total time %f\n", rc.total_ticks / 16000000.0);
|
||||
|
||||
#if (TEST_CREATE_QUEUE_CHECKSUM == 1)
|
||||
printf("CHECKSUM for %d/%d/%d: %d\n", steps, travel_dt, accel, s.checksum);
|
||||
#endif
|
||||
}
|
||||
};
|
||||
int main() {
|
||||
FastAccelStepperTest test;
|
||||
for (uint16_t s = 1; s <= 255; s++) {
|
||||
printf("test with steps s=%d\n", s);
|
||||
test.ramp(INT32_MAX, 50, s, false);
|
||||
puts("");
|
||||
}
|
||||
printf("TEST_13 PASSED\n");
|
||||
return 0;
|
||||
}
|
||||
106
extras/tests/pc_based/test_14.cpp
Normal file
106
extras/tests/pc_based/test_14.cpp
Normal file
@@ -0,0 +1,106 @@
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "FastAccelStepper.h"
|
||||
#include "StepperISR.h"
|
||||
|
||||
char TCCR1A;
|
||||
char TCCR1B;
|
||||
char TCCR1C;
|
||||
char TIMSK1;
|
||||
char TIFR1;
|
||||
unsigned short OCR1A;
|
||||
unsigned short OCR1B;
|
||||
|
||||
StepperQueue fas_queue[NUM_QUEUES];
|
||||
|
||||
void inject_fill_interrupt(int mark) {}
|
||||
void noInterrupts() {}
|
||||
void interrupts() {}
|
||||
|
||||
#include "RampChecker.h"
|
||||
|
||||
class FastAccelStepperTest {
|
||||
public:
|
||||
void init_queue() {
|
||||
fas_queue[0].read_idx = 0;
|
||||
fas_queue[1].read_idx = 0;
|
||||
fas_queue[0].next_write_idx = 0;
|
||||
fas_queue[1].next_write_idx = 0;
|
||||
}
|
||||
|
||||
void ramp() {
|
||||
init_queue();
|
||||
FastAccelStepper s = FastAccelStepper();
|
||||
s.init(NULL, 0, 0);
|
||||
RampChecker rc = RampChecker();
|
||||
assert(0 == s.getCurrentPosition());
|
||||
|
||||
uint32_t speed_us = 1000000 / 3600;
|
||||
assert(s.isQueueEmpty());
|
||||
s.setSpeedInUs(speed_us);
|
||||
s.setAcceleration(320);
|
||||
s.fill_queue();
|
||||
assert(s.isQueueEmpty());
|
||||
float old_planned_time_in_buffer = 0;
|
||||
|
||||
char fname[100];
|
||||
snprintf(fname, 100, "test_14.gnuplot");
|
||||
rc.start_plot(fname);
|
||||
s.runForward();
|
||||
for (int i = 0; i < 2000; i++) {
|
||||
if (i == 1000) {
|
||||
printf("Change speed\n");
|
||||
s.setSpeedInUs(10000);
|
||||
s.applySpeedAcceleration();
|
||||
}
|
||||
if (true) {
|
||||
printf(
|
||||
"Loop %d: Queue read/write = %d/%d Target pos = %d, Queue End "
|
||||
"pos = %d QueueEmpty=%s\n",
|
||||
i, fas_queue[0].read_idx, fas_queue[0].next_write_idx,
|
||||
s.targetPos(), s.getPositionAfterCommandsCompleted(),
|
||||
s.isQueueEmpty() ? "yes" : "no");
|
||||
}
|
||||
if (!s.isRampGeneratorActive()) {
|
||||
break;
|
||||
}
|
||||
s.fill_queue();
|
||||
uint32_t from_dt = rc.total_ticks;
|
||||
while (!s.isQueueEmpty()) {
|
||||
rc.increase_ok = true;
|
||||
rc.decrease_ok = true;
|
||||
rc.check_section(
|
||||
&fas_queue[0].entry[fas_queue[0].read_idx & QUEUE_LEN_MASK]);
|
||||
fas_queue[0].read_idx++;
|
||||
}
|
||||
uint32_t to_dt = rc.total_ticks;
|
||||
float planned_time = (to_dt - from_dt) * 1.0 / 16000000;
|
||||
printf("planned time in buffer: %.6fs\n", planned_time);
|
||||
// This must be ensured, so that the stepper does not run out of
|
||||
// commands
|
||||
assert((i == 0) || (old_planned_time_in_buffer > 0.005));
|
||||
old_planned_time_in_buffer = planned_time;
|
||||
// stop after
|
||||
if (rc.total_ticks > TICKS_PER_S * 40) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
rc.finish_plot();
|
||||
// test(!s.isRampGeneratorActive(), "too many commands created");
|
||||
test(s.getCurrentPosition() > 70000, "stepper runs too slow");
|
||||
test(s.getCurrentPosition() < 80000, "stepper runs too fast");
|
||||
printf("Total time %f\n", rc.total_ticks / 16000000.0);
|
||||
|
||||
#if (TEST_CREATE_QUEUE_CHECKSUM == 1)
|
||||
printf("CHECKSUM for %d/%d/%d: %d\n", steps, travel_dt, accel, s.checksum);
|
||||
#endif
|
||||
}
|
||||
};
|
||||
int main() {
|
||||
FastAccelStepperTest test;
|
||||
test.ramp();
|
||||
printf("TEST_14 PASSED\n");
|
||||
return 0;
|
||||
}
|
||||
119
extras/tests/pc_based/test_15.cpp
Normal file
119
extras/tests/pc_based/test_15.cpp
Normal file
@@ -0,0 +1,119 @@
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "FastAccelStepper.h"
|
||||
#include "StepperISR.h"
|
||||
|
||||
char TCCR1A;
|
||||
char TCCR1B;
|
||||
char TCCR1C;
|
||||
char TIMSK1;
|
||||
char TIFR1;
|
||||
unsigned short OCR1A;
|
||||
unsigned short OCR1B;
|
||||
|
||||
StepperQueue fas_queue[NUM_QUEUES];
|
||||
|
||||
void inject_fill_interrupt(int mark) {}
|
||||
void noInterrupts() {}
|
||||
void interrupts() {}
|
||||
|
||||
#include "RampChecker.h"
|
||||
|
||||
class FastAccelStepperTest {
|
||||
public:
|
||||
void init_queue() {
|
||||
fas_queue[0].read_idx = 0;
|
||||
fas_queue[1].read_idx = 0;
|
||||
fas_queue[0].next_write_idx = 0;
|
||||
fas_queue[1].next_write_idx = 0;
|
||||
}
|
||||
|
||||
void ramp(uint8_t forward_planning, uint32_t expected_steps) {
|
||||
init_queue();
|
||||
FastAccelStepper s = FastAccelStepper();
|
||||
s.init(NULL, 0, 0);
|
||||
RampChecker rc = RampChecker();
|
||||
assert(0 == s.getCurrentPosition());
|
||||
|
||||
uint32_t speed_us = 1000000 / 3600;
|
||||
assert(s.isQueueEmpty());
|
||||
s.setSpeedInUs(speed_us);
|
||||
s.setAcceleration(320);
|
||||
s.setForwardPlanningTimeInMs(forward_planning);
|
||||
s.fill_queue();
|
||||
assert(s.isQueueEmpty());
|
||||
float old_planned_time_in_buffer = 0;
|
||||
|
||||
char fname[100];
|
||||
float sum_planning_time = 0;
|
||||
float points = 0;
|
||||
snprintf(fname, 100, "test_15_%dms.gnuplot", forward_planning);
|
||||
rc.start_plot(fname);
|
||||
s.runForward();
|
||||
for (int i = 0; i < 2000; i++) {
|
||||
if (i == 1000) {
|
||||
printf("Change speed\n");
|
||||
s.setSpeedInUs(10000);
|
||||
s.applySpeedAcceleration();
|
||||
}
|
||||
if (true) {
|
||||
printf(
|
||||
"Loop %d: Queue read/write = %d/%d Target pos = %d, Queue End "
|
||||
"pos = %d QueueEmpty=%s\n",
|
||||
i, fas_queue[0].read_idx, fas_queue[0].next_write_idx,
|
||||
s.targetPos(), s.getPositionAfterCommandsCompleted(),
|
||||
s.isQueueEmpty() ? "yes" : "no");
|
||||
}
|
||||
if (!s.isRampGeneratorActive()) {
|
||||
break;
|
||||
}
|
||||
s.fill_queue();
|
||||
uint32_t from_dt = rc.total_ticks;
|
||||
while (!s.isQueueEmpty()) {
|
||||
rc.increase_ok = true;
|
||||
rc.decrease_ok = true;
|
||||
rc.check_section(
|
||||
&fas_queue[0].entry[fas_queue[0].read_idx & QUEUE_LEN_MASK]);
|
||||
fas_queue[0].read_idx++;
|
||||
}
|
||||
uint32_t to_dt = rc.total_ticks;
|
||||
float planned_time = (to_dt - from_dt) * 1.0 / 16000000;
|
||||
printf("planned time in buffer: %.6fs\n", planned_time);
|
||||
sum_planning_time += planned_time;
|
||||
points += 1.0;
|
||||
// This must be ensured, so that the stepper does not run out of
|
||||
// commands
|
||||
assert((i == 0) || (old_planned_time_in_buffer > 0.005));
|
||||
old_planned_time_in_buffer = planned_time;
|
||||
// stop after
|
||||
if (rc.total_ticks > TICKS_PER_S * 40) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
rc.finish_plot();
|
||||
// test(!s.isRampGeneratorActive(), "too many commands created");
|
||||
printf("current position = %d\n", s.getCurrentPosition());
|
||||
test(s.getCurrentPosition() > expected_steps - 10, "stepper runs too slow");
|
||||
test(s.getCurrentPosition() < expected_steps + 10, "stepper runs too fast");
|
||||
printf("Total time %f\n", rc.total_ticks / 16000000.0);
|
||||
float avg_time = sum_planning_time / points * 1000.0;
|
||||
printf("Average planning time: %f ms\n", avg_time);
|
||||
test(avg_time < forward_planning + 1, "too much forward planning");
|
||||
|
||||
#if (TEST_CREATE_QUEUE_CHECKSUM == 1)
|
||||
printf("CHECKSUM for %d/%d/%d: %d\n", steps, travel_dt, accel, s.checksum);
|
||||
#endif
|
||||
}
|
||||
};
|
||||
int main() {
|
||||
FastAccelStepperTest test;
|
||||
// run the ramp twice with 20 and with 5ms planning time.
|
||||
// the ramp will change speed after half of the loops.
|
||||
// The 5ms ramp will not have 20ms coasting in the buffer and as such runs much shorter.
|
||||
test.ramp(20, 76936);
|
||||
test.ramp(5, 11273);
|
||||
printf("TEST_15 PASSED\n");
|
||||
return 0;
|
||||
}
|
||||
2
extras/tests/simavr_based/.gitignore
vendored
Normal file
2
extras/tests/simavr_based/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
.links
|
||||
.makefiles
|
||||
62
extras/tests/simavr_based/Makefile
Normal file
62
extras/tests/simavr_based/Makefile
Normal file
@@ -0,0 +1,62 @@
|
||||
ifndef SILENCE
|
||||
SILENCE=0
|
||||
endif
|
||||
|
||||
PRJ_ROOT=$(shell git rev-parse --show-toplevel)
|
||||
TESTS=$(wildcard test_*)
|
||||
TESTS_SD=$(wildcard test_*sd_*)
|
||||
|
||||
TEST_FILES=$(addsuffix /.tested,$(TESTS))
|
||||
SD_SRC_DIRS=$(addsuffix /src/.dir,$(TESTS_SD))
|
||||
|
||||
SRC=$(wildcard ../../src/*)
|
||||
|
||||
test: $(TEST_FILES) pmf externalCall
|
||||
|
||||
pmf:
|
||||
make -C test_pmf
|
||||
|
||||
externalCall:
|
||||
make -C test_externalCall
|
||||
|
||||
%/.tested: $(SRC) run_avr %/expect.txt %/platformio.ini .makefiles .links
|
||||
make SILENCE=$(SILENCE) -C $(dir $@)
|
||||
|
||||
.makefiles: makefiles
|
||||
|
||||
makefiles: $(addsuffix /Makefile,$(TESTS))
|
||||
touch .makefiles
|
||||
|
||||
%/Makefile:
|
||||
cd $(dir $@); ln -s ../Makefile.test Makefile
|
||||
|
||||
.links: links
|
||||
|
||||
links: $(SD_SRC_DIRS)
|
||||
touch .links
|
||||
|
||||
%/src/.dir:
|
||||
mkdir -p $(dir $@)
|
||||
cd $(dir $@); ln -sf $(PRJ_ROOT)/examples/StepperDemo/* .
|
||||
|
||||
run_avr: simavr/simavr/run_avr
|
||||
ln -s simavr/simavr/run_avr .
|
||||
|
||||
simavr/simavr/run_avr: simavr/simavr/sim/run_avr.c
|
||||
make -C simavr build-simavr
|
||||
|
||||
simavr/simavr/sim/run_avr.c:
|
||||
# git clone https://github.com/gin66/simavr.git
|
||||
git clone https://github.com/buserror/simavr.git
|
||||
(cd simavr;git checkout 132cc67)
|
||||
|
||||
proper: clean
|
||||
rm -f run_avr
|
||||
rm -fR simavr
|
||||
|
||||
clean:
|
||||
rm -fR */.pio */.tested */x.vcd */result.txt
|
||||
find . -type l -delete
|
||||
find . -type d -empty -delete
|
||||
rm -f .links .makefiles
|
||||
|
||||
127
extras/tests/simavr_based/Makefile.test
Normal file
127
extras/tests/simavr_based/Makefile.test
Normal file
@@ -0,0 +1,127 @@
|
||||
#
|
||||
# In order to execute the test for one directory use:
|
||||
#
|
||||
# make -C test_sd_01b_328p -f ../Makefile.test
|
||||
|
||||
SRC=$(wildcard ../../../src/*) $(wildcard src/*)
|
||||
|
||||
# platformio should contain only one env section.
|
||||
# This section states the dut name
|
||||
# atmega168
|
||||
# atmega168p
|
||||
# atmega328
|
||||
# atmega328p
|
||||
# atmega2560_timer1
|
||||
# atmega2560_timer3
|
||||
# atmega2560_timer4
|
||||
# atmega2560_timer5
|
||||
#
|
||||
|
||||
DUT=$(shell gawk '/env:/{print(substr($$1,6,length($$1)-6))}' platformio.ini)
|
||||
|
||||
TRACES=-at StepISR=trace@0x25/0x08 # PB3
|
||||
TRACES+=-at FillISR=trace@0x25/0x10 # PB4
|
||||
|
||||
#
|
||||
ifeq ($(DUT),atmega2560_timer1)
|
||||
DEVICE=atmega2560
|
||||
TRACES+=-at StepA=trace@0x025/0x20 #OC1A PB5 11 ATMega2560
|
||||
TRACES+=-at StepB=trace@0x025/0x40 #OC1B PB6 12 ATMega2560
|
||||
TRACES+=-at StepC=trace@0x025/0x80 #OC1C PB7 13 ATMega2560
|
||||
#
|
||||
else ifeq ($(DUT),atmega2560_timer3)
|
||||
DEVICE=atmega2560
|
||||
TRACES+=-at StepA=trace@0x02e/0x08 #OC3A PE3 5 ATMega2560
|
||||
TRACES+=-at StepB=trace@0x02e/0x10 #OC3B PE4 2 ATMega2560
|
||||
TRACES+=-at StepC=trace@0x02e/0x20 #OC3C PE5 3 ATMega2560
|
||||
#
|
||||
else ifeq ($(DUT),atmega2560_timer4)
|
||||
DEVICE=atmega2560
|
||||
TRACES+=-at StepA=trace@0x102/0x08 #OC4A PH3 6 ATMega2560
|
||||
TRACES+=-at StepB=trace@0x102/0x10 #OC4B PH4 7 ATMega2560
|
||||
TRACES+=-at StepC=trace@0x102/0x20 #OC4C PH5 8 ATMega2560
|
||||
#
|
||||
else ifeq ($(DUT),atmega2560_timer5)
|
||||
DEVICE=atmega2560
|
||||
TRACES+=-at StepA=trace@0x10b/0x08 #OC5A PL3 46 ATMega2560
|
||||
TRACES+=-at StepB=trace@0x10b/0x10 #OC5B PL4 45 ATMega2560
|
||||
TRACES+=-at StepC=trace@0x10b/0x20 #OC5C PL5 44 ATMega2560
|
||||
|
||||
else ifeq ($(DUT),atmega168)
|
||||
DEVICE=atmega168
|
||||
TRACES+=-at StepA=trace@0x25/0x02 #OC1A PB1 9 ATMega168
|
||||
TRACES+=-at StepB=trace@0x25/0x04 #OC1B PB2 10 ATMega168
|
||||
|
||||
else ifeq ($(DUT),atmega168p)
|
||||
DEVICE=atmega168p
|
||||
TRACES+=-at StepA=trace@0x25/0x02 #OC1A PB1 9 ATMega168p
|
||||
TRACES+=-at StepB=trace@0x25/0x04 #OC1B PB2 10 ATMega168p
|
||||
|
||||
else ifeq ($(DUT),atmega328)
|
||||
DEVICE=atmega328
|
||||
TRACES+=-at StepA=trace@0x25/0x02 #OC1A PB1 9 ATMega328
|
||||
TRACES+=-at StepB=trace@0x25/0x04 #OC1B PB2 10 ATMega328
|
||||
|
||||
else ifeq ($(DUT),atmega328p)
|
||||
DEVICE=atmega328p
|
||||
TRACES+=-at StepA=trace@0x25/0x02 #OC1A PB1 9 ATMega328p
|
||||
TRACES+=-at StepB=trace@0x25/0x04 #OC1B PB2 10 ATMega328p
|
||||
|
||||
else ifeq ($(DUT),atmega32u4)
|
||||
DEVICE=atmega32u4
|
||||
TRACES+=-at StepA=trace@0x025/0x20 #OC1A PB5 11
|
||||
TRACES+=-at StepB=trace@0x025/0x40 #OC1B PB6 12
|
||||
#TRACES+=-at StepC=trace@0x025/0x80 #OC1C PB7 13
|
||||
|
||||
endif
|
||||
|
||||
ifeq ($(DEVICE),atmega2560)
|
||||
TRACES+=-at DirA=trace@0x2b/0x01 # Pin 21 PD0
|
||||
TRACES+=-at DirB=trace@0x2b/0x02 # Pin 20 PD1
|
||||
TRACES+=-at DirC=trace@0x10b/0x80 # Pin 42 PL7
|
||||
TRACES+=-at EnableA=trace@0x2b/0x04 # Pin 19 PD2
|
||||
TRACES+=-at EnableB=trace@0x2b/0x08 # Pin 18 PD3
|
||||
TRACES+=-at EnableC=trace@0x10b/0x40 # Pin 43 PL6
|
||||
|
||||
else ifeq ($(DEVICE),$(filter $(DEVICE),atmega168 atmega168p atmega328 atmega328p))
|
||||
TRACES+=-at DirA=trace@0x2b/0x20 # Pin 5 PD5
|
||||
TRACES+=-at DirB=trace@0x2b/0x80 # Pin 7 PD7
|
||||
TRACES+=-at EnableA=trace@0x2b/0x40 # Pin 6 PD6
|
||||
TRACES+=-at EnableB=trace@0x25/0x01 # Pin 0 PB0
|
||||
|
||||
else ifeq ($(DUT),atmega32u4)
|
||||
TRACES+=-at DirA=trace@0x25/0x10 # Pin 26 PB4
|
||||
TRACES+=-at DirB=trace@0x25/0x08 # Pin 14 PB3
|
||||
#TRACES+=-at DirC=trace@0x10b/0x80 # Pin 42 PL7
|
||||
TRACES+=-at EnableA=trace@0x25/0x04 # Pin 16 PB2
|
||||
TRACES+=-at EnableB=trace@0x25/0x02 # Pin 15 PB1
|
||||
#TRACES+=-at EnableC=trace@0x10b/0x40 # Pin 43 PL6
|
||||
|
||||
endif
|
||||
|
||||
FIRMWARE=".pio/build/$(DUT)/firmware.elf"
|
||||
|
||||
DIR=$(shell env pwd)
|
||||
|
||||
ifndef SILENCE
|
||||
SILENCE=0
|
||||
endif
|
||||
|
||||
test: .tested
|
||||
|
||||
.tested: result.txt expect.txt ../judge.awk
|
||||
echo DUT=$(DUT)
|
||||
rm -f .tested
|
||||
gawk -f ../judge.awk -v DIR=$(DIR) result.txt expect.txt
|
||||
test -f .tested
|
||||
|
||||
result.txt: x.vcd
|
||||
gawk -v SILENCE=$(SILENCE) -f ../eval.awk x.vcd
|
||||
cat expect.txt
|
||||
|
||||
x.vcd: $(SRC) ../run_avr platformio.ini
|
||||
env pio run -e $(DUT) || ~/.platformio/penv/bin/pio run -e $(DUT) || ~/.local/bin/pio run -e $(DUT)
|
||||
../run_avr $(FIRMWARE) -m $(DEVICE) -o x.vcd $(TRACES)
|
||||
|
||||
clean:
|
||||
rm -fR .pio .tested x.vcd result.txt
|
||||
31
extras/tests/simavr_based/Raw/platformio.ini
Normal file
31
extras/tests/simavr_based/Raw/platformio.ini
Normal file
@@ -0,0 +1,31 @@
|
||||
; PlatformIO Project Configuration File
|
||||
;
|
||||
; Build options: build flags, source filter
|
||||
; Upload options: custom upload port, speed and extra flags
|
||||
; Library options: dependencies, extra library storages
|
||||
; Advanced options: extra scripting
|
||||
;
|
||||
; Please visit documentation for the other options and examples
|
||||
; https://docs.platformio.org/page/projectconf.html
|
||||
|
||||
[platformio]
|
||||
|
||||
# There should be only one env section for the DUT under test.
|
||||
# One of
|
||||
# atmega168p
|
||||
# atmega328p
|
||||
# atmega2560_timer1
|
||||
# atmega2560_timer3
|
||||
# atmega2560_timer4
|
||||
# atmega2560_timer5
|
||||
#
|
||||
[common]
|
||||
# This is the line input to StepperDemo:
|
||||
build_flags = -D SIM_TEST_INPUT='"? M1 V60 A40000 f w400 A40000 P0 w1000 W "'
|
||||
|
||||
[env:atmega328p]
|
||||
platform = atmelavr
|
||||
board = nanoatmega328
|
||||
framework = arduino
|
||||
build_flags = -Werror -Wall ${common.build_flags}
|
||||
lib_extra_dirs = ../../../../..
|
||||
128
extras/tests/simavr_based/eval.awk
Normal file
128
extras/tests/simavr_based/eval.awk
Normal file
@@ -0,0 +1,128 @@
|
||||
BEGIN {
|
||||
ref = 16*100
|
||||
dump_all = 0
|
||||
}
|
||||
|
||||
dump_all == 1{print}
|
||||
|
||||
/^\$var wire 1/ {
|
||||
names[++name_i] = $5
|
||||
sym[$4] = $5
|
||||
to_sym[$5] = $4
|
||||
period_hl_hl[$4] = 0
|
||||
period_lh_lh[$4] = 0
|
||||
time_h[$4] = 0
|
||||
time_l[$4] = 0
|
||||
transition_l_h[$4] = 0
|
||||
transition_h_l[$4] = 0
|
||||
cnt_l_h[$4] = 0
|
||||
cnt_h_l[$4] = 0
|
||||
max_time_h[$4] = 0
|
||||
sum_time_h[$4] = 0
|
||||
state[$4] = "X"
|
||||
}
|
||||
|
||||
/^#/ { time = substr($1,2) + 0 }
|
||||
|
||||
/^1.$/ {
|
||||
s = substr($1,2)
|
||||
if(!SILENCE) printf("%s=1 ", sym[s])
|
||||
if (state[s] == 0) {
|
||||
# transition L->H
|
||||
cnt_l_h[s]++
|
||||
last = transition_l_h[s]
|
||||
transition_l_h[s] = time
|
||||
if (last > 0) {
|
||||
period_lh_lh[s] = time - last
|
||||
}
|
||||
last = transition_h_l[s]
|
||||
if (last > 0) {
|
||||
time_l[s] = time - last
|
||||
}
|
||||
|
||||
if (sym[s] ~ /Step/) {
|
||||
channel = substr(sym[s],5)
|
||||
if(!SILENCE) printf("%s: ", channel)
|
||||
dir = "Dir" channel
|
||||
if (dir in to_sym) {
|
||||
dir_sym = to_sym[dir]
|
||||
if (state[dir_sym] == 0) {
|
||||
position[channel]--
|
||||
}
|
||||
else {
|
||||
position[channel]++
|
||||
}
|
||||
if(!SILENCE) printf("position=%d ",position[channel])
|
||||
}
|
||||
if(!SILENCE) printf("period=%.1fus high time=%.1fus",
|
||||
period_lh_lh[s]/ref,time_h[s]/ref)
|
||||
}
|
||||
}
|
||||
if(!SILENCE) printf("\n")
|
||||
state[s] = 1
|
||||
}
|
||||
/^0.$/ {
|
||||
s = substr($1,2)
|
||||
if(!SILENCE) printf("%s=0 ", sym[s])
|
||||
if (state[s] == 1) {
|
||||
# transition H->L
|
||||
cnt_h_l[s]++
|
||||
last = transition_h_l[s]
|
||||
transition_h_l[s] = time
|
||||
if (last > 0) {
|
||||
period_hl_hl[s] = time - last
|
||||
}
|
||||
last = transition_l_h[s]
|
||||
if (last > 0) {
|
||||
time_h[s] = time - last
|
||||
}
|
||||
if (sym[s] ~ /FillISR/) {
|
||||
if(!SILENCE) printf("period=%.1fus ", period_lh_lh[s]/ref)
|
||||
}
|
||||
h_time = time_h[s]/ref
|
||||
if(!SILENCE) printf("high time=%.1fus", h_time)
|
||||
sum_time_h[s] += h_time
|
||||
if (h_time > max_time_h[s]) {
|
||||
max_time_h[s] = h_time
|
||||
}
|
||||
}
|
||||
if(!SILENCE) printf("\n")
|
||||
state[s] = 0
|
||||
}
|
||||
|
||||
END {
|
||||
n = asort(names)
|
||||
for (i = 1;i <= n;i++) {
|
||||
name = names[i]
|
||||
s = to_sym[name]
|
||||
info = sprintf("%8s: %8d*L->H, %8d*H->L",name,cnt_l_h[s],cnt_h_l[s])
|
||||
if (name ~ /Step/) {
|
||||
info = sprintf("%s, Max High=%dus Total High=%dus", info, max_time_h[s], sum_time_h[s])
|
||||
}
|
||||
if(!SILENCE) print(info)
|
||||
if (name !~ /ISR/) {
|
||||
print(info) >"result.txt"
|
||||
}
|
||||
}
|
||||
channels["A"]=1
|
||||
channels["B"]=1
|
||||
channels["C"]=1
|
||||
for (ch in channels) {
|
||||
if (ch in position) {
|
||||
info = sprintf("Position[%s]=%d\n",ch,position[ch])
|
||||
if(!SILENCE) print(info)
|
||||
print(info) >"result.txt"
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 1;i <= n;i++) {
|
||||
name = names[i]
|
||||
s = to_sym[name]
|
||||
if (max_time_h[s] > 0) {
|
||||
info = sprintf("Time in %s max=%d us, total=%d us\n",name,max_time_h[s], sum_time_h[s])
|
||||
if(!SILENCE) print(info)
|
||||
print(info) >"result.txt"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
38
extras/tests/simavr_based/judge.awk
Normal file
38
extras/tests/simavr_based/judge.awk
Normal file
@@ -0,0 +1,38 @@
|
||||
BEGIN {
|
||||
ok = 1
|
||||
timing = 0
|
||||
if (DIR ~ /timing/) {
|
||||
timing = 1
|
||||
}
|
||||
}
|
||||
|
||||
FNR == NR {
|
||||
# result.txt
|
||||
lines[FNR] = $0
|
||||
}
|
||||
|
||||
FNR != NR {
|
||||
# expect.txt
|
||||
r = lines[FNR]
|
||||
e = $0
|
||||
|
||||
r_test = r
|
||||
e_test = e
|
||||
|
||||
if (timing == 0) {
|
||||
gsub(/[0-9 ]*us/,"", r_test)
|
||||
gsub(/[0-9 ]*us/,"", e_test)
|
||||
}
|
||||
if (e_test != r_test) {
|
||||
print("result:",r)
|
||||
print("expect:",e)
|
||||
ok = 0
|
||||
}
|
||||
}
|
||||
|
||||
END {
|
||||
if (ok == 1) {
|
||||
print("PASS")
|
||||
print("PASS") > ".tested"
|
||||
}
|
||||
}
|
||||
22
extras/tests/simavr_based/judge_pos0.awk
Normal file
22
extras/tests/simavr_based/judge_pos0.awk
Normal file
@@ -0,0 +1,22 @@
|
||||
BEGIN {
|
||||
ok = 0
|
||||
}
|
||||
|
||||
FNR == NR {
|
||||
# result.txt
|
||||
lines[FNR] = $0
|
||||
}
|
||||
|
||||
/^Position\[A\]/ {
|
||||
print
|
||||
}
|
||||
$0 == "Position[A]=0" {
|
||||
ok = 1
|
||||
}
|
||||
|
||||
END {
|
||||
if (ok == 1) {
|
||||
print("PASS")
|
||||
print("PASS") > ".tested"
|
||||
}
|
||||
}
|
||||
26
extras/tests/simavr_based/off_test_seq_03/platformio.ini
Normal file
26
extras/tests/simavr_based/off_test_seq_03/platformio.ini
Normal file
@@ -0,0 +1,26 @@
|
||||
; PlatformIO Project Configuration File
|
||||
;
|
||||
; Build options: build flags, source filter
|
||||
; Upload options: custom upload port, speed and extra flags
|
||||
; Library options: dependencies, extra library storages
|
||||
; Advanced options: extra scripting
|
||||
;
|
||||
; Please visit documentation for the other options and examples
|
||||
; https://docs.platformio.org/page/projectconf.html
|
||||
|
||||
[platformio]
|
||||
|
||||
[env:avr]
|
||||
platform = atmelavr
|
||||
board = nanoatmega328
|
||||
framework = arduino
|
||||
build_flags = -Werror -Wall -D SIM_TEST_INPUT='"t M1 03 I R W "' -DSIMAVR_FOC_WORKAROUND
|
||||
lib_extra_dirs = ../../../../..
|
||||
|
||||
[env:atmega2560]
|
||||
platform = atmelavr
|
||||
board = megaatmega2560
|
||||
framework = arduino
|
||||
build_flags = -Werror -Wall
|
||||
lib_extra_dirs = ../../../../..
|
||||
|
||||
26
extras/tests/simavr_based/off_test_seq_04/platformio.ini
Normal file
26
extras/tests/simavr_based/off_test_seq_04/platformio.ini
Normal file
@@ -0,0 +1,26 @@
|
||||
; PlatformIO Project Configuration File
|
||||
;
|
||||
; Build options: build flags, source filter
|
||||
; Upload options: custom upload port, speed and extra flags
|
||||
; Library options: dependencies, extra library storages
|
||||
; Advanced options: extra scripting
|
||||
;
|
||||
; Please visit documentation for the other options and examples
|
||||
; https://docs.platformio.org/page/projectconf.html
|
||||
|
||||
[platformio]
|
||||
|
||||
[env:avr]
|
||||
platform = atmelavr
|
||||
board = nanoatmega328
|
||||
framework = arduino
|
||||
build_flags = -Werror -Wall -D SIM_TEST_INPUT='"t M1 04 I R W "' -DSIMAVR_FOC_WORKAROUND
|
||||
lib_extra_dirs = ../../../../..
|
||||
|
||||
[env:atmega2560]
|
||||
platform = atmelavr
|
||||
board = megaatmega2560
|
||||
framework = arduino
|
||||
build_flags = -Werror -Wall
|
||||
lib_extra_dirs = ../../../../..
|
||||
|
||||
26
extras/tests/simavr_based/off_test_seq_05/platformio.ini
Normal file
26
extras/tests/simavr_based/off_test_seq_05/platformio.ini
Normal file
@@ -0,0 +1,26 @@
|
||||
; PlatformIO Project Configuration File
|
||||
;
|
||||
; Build options: build flags, source filter
|
||||
; Upload options: custom upload port, speed and extra flags
|
||||
; Library options: dependencies, extra library storages
|
||||
; Advanced options: extra scripting
|
||||
;
|
||||
; Please visit documentation for the other options and examples
|
||||
; https://docs.platformio.org/page/projectconf.html
|
||||
|
||||
[platformio]
|
||||
|
||||
[env:avr]
|
||||
platform = atmelavr
|
||||
board = nanoatmega328
|
||||
framework = arduino
|
||||
build_flags = -Werror -Wall -D SIM_TEST_INPUT='"t M1 05 I R W "' -DSIMAVR_FOC_WORKAROUND
|
||||
lib_extra_dirs = ../../../../..
|
||||
|
||||
[env:atmega2560]
|
||||
platform = atmelavr
|
||||
board = megaatmega2560
|
||||
framework = arduino
|
||||
build_flags = -Werror -Wall
|
||||
lib_extra_dirs = ../../../../..
|
||||
|
||||
30
extras/tests/simavr_based/off_test_timing/platformio.ini
Normal file
30
extras/tests/simavr_based/off_test_timing/platformio.ini
Normal file
@@ -0,0 +1,30 @@
|
||||
; PlatformIO Project Configuration File
|
||||
;
|
||||
; Build options: build flags, source filter
|
||||
; Upload options: custom upload port, speed and extra flags
|
||||
; Library options: dependencies, extra library storages
|
||||
; Advanced options: extra scripting
|
||||
;
|
||||
; Please visit documentation for the other options and examples
|
||||
; https://docs.platformio.org/page/projectconf.html
|
||||
|
||||
[platformio]
|
||||
|
||||
# There should be only one env section for the DUT under test.
|
||||
# One of
|
||||
# atmega168p
|
||||
# atmega328p
|
||||
# atmega2560_timer1
|
||||
# atmega2560_timer3
|
||||
# atmega2560_timer4
|
||||
# atmega2560_timer5
|
||||
#
|
||||
[common]
|
||||
build_flags = -DTEST_TIMING
|
||||
|
||||
[env:atmega328p]
|
||||
platform = atmelavr
|
||||
board = nanoatmega328
|
||||
framework = arduino
|
||||
build_flags = -Werror -Wall -DSIMAVR_FOC_WORKAROUND ${common.build_flags}
|
||||
lib_extra_dirs = ../../../../..
|
||||
40
extras/tests/simavr_based/off_test_timing/src/main.ino
Normal file
40
extras/tests/simavr_based/off_test_timing/src/main.ino
Normal file
@@ -0,0 +1,40 @@
|
||||
#include <avr/sleep.h>
|
||||
#include <AVRStepperPins.h>
|
||||
#include <RampCalculator.h>
|
||||
|
||||
float acceleration_f;
|
||||
uint32_t acceleration_i;
|
||||
uint32_t steps;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
Serial.println("Start");
|
||||
|
||||
digitalWrite(stepPinStepperA, LOW);
|
||||
digitalWrite(stepPinStepperB, LOW);
|
||||
pinMode(stepPinStepperA, OUTPUT);
|
||||
pinMode(stepPinStepperB, OUTPUT);
|
||||
|
||||
acceleration_f = 12345.0;
|
||||
acceleration_i = 12345.0;
|
||||
steps = 10;
|
||||
}
|
||||
void loop() {
|
||||
digitalWrite(stepPinStepperA, HIGH);
|
||||
uint32_t x;
|
||||
// x = calculate_ticks_v1(steps, acceleration_f);
|
||||
// x = calculate_ticks_v2(steps, acceleration_f);
|
||||
// x = calculate_ticks_v3(steps, acceleration_f);
|
||||
// x = calculate_ticks_v4(steps, acceleration_i);
|
||||
// x = calculate_ticks_v5(steps, acceleration_i);
|
||||
// x = calculate_ticks_v7(0x1234000, 1000);
|
||||
x = calculate_ticks_v8(0x1234000, 1000);
|
||||
digitalWrite(stepPinStepperA, LOW);
|
||||
|
||||
digitalWrite(stepPinStepperB, HIGH);
|
||||
digitalWrite(stepPinStepperB, LOW);
|
||||
Serial.println(x);
|
||||
delay(100);
|
||||
noInterrupts();
|
||||
sleep_cpu();
|
||||
}
|
||||
1
extras/tests/simavr_based/test_externalCall/.gitignore
vendored
Normal file
1
extras/tests/simavr_based/test_externalCall/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
src/
|
||||
131
extras/tests/simavr_based/test_externalCall/Makefile
Normal file
131
extras/tests/simavr_based/test_externalCall/Makefile
Normal file
@@ -0,0 +1,131 @@
|
||||
#
|
||||
# In order to execute the test for one directory use:
|
||||
#
|
||||
# make -C test_sd_01b_328p -f ../Makefile.test
|
||||
|
||||
SRC=$(wildcard ../../../src/*) $(wildcard src/*)
|
||||
|
||||
# platformio should contain only one env section.
|
||||
# This section states the dut name
|
||||
# atmega168
|
||||
# atmega168p
|
||||
# atmega328
|
||||
# atmega328p
|
||||
# atmega2560_timer1
|
||||
# atmega2560_timer3
|
||||
# atmega2560_timer4
|
||||
# atmega2560_timer5
|
||||
#
|
||||
|
||||
DUT=$(shell gawk '/env:/{print(substr($$1,6,length($$1)-6))}' platformio.ini)
|
||||
|
||||
TRACES=-at StepISR=trace@0x25/0x08 # PB3
|
||||
TRACES+=-at FillISR=trace@0x25/0x10 # PB4
|
||||
|
||||
#
|
||||
ifeq ($(DUT),atmega2560_timer1)
|
||||
DEVICE=atmega2560
|
||||
TRACES+=-at StepA=trace@0x025/0x20 #OC1A PB5 11 ATMega2560
|
||||
TRACES+=-at StepB=trace@0x025/0x40 #OC1B PB6 12 ATMega2560
|
||||
TRACES+=-at StepC=trace@0x025/0x80 #OC1C PB7 13 ATMega2560
|
||||
#
|
||||
else ifeq ($(DUT),atmega2560_timer3)
|
||||
DEVICE=atmega2560
|
||||
TRACES+=-at StepA=trace@0x02e/0x08 #OC3A PE3 5 ATMega2560
|
||||
TRACES+=-at StepB=trace@0x02e/0x10 #OC3B PE4 2 ATMega2560
|
||||
TRACES+=-at StepC=trace@0x02e/0x20 #OC3C PE5 3 ATMega2560
|
||||
#
|
||||
else ifeq ($(DUT),atmega2560_timer4)
|
||||
DEVICE=atmega2560
|
||||
TRACES+=-at StepA=trace@0x102/0x08 #OC4A PH3 6 ATMega2560
|
||||
TRACES+=-at StepB=trace@0x102/0x10 #OC4B PH4 7 ATMega2560
|
||||
TRACES+=-at StepC=trace@0x102/0x20 #OC4C PH5 8 ATMega2560
|
||||
#
|
||||
else ifeq ($(DUT),atmega2560_timer5)
|
||||
DEVICE=atmega2560
|
||||
TRACES+=-at StepA=trace@0x10b/0x08 #OC5A PL3 46 ATMega2560
|
||||
TRACES+=-at StepB=trace@0x10b/0x10 #OC5B PL4 45 ATMega2560
|
||||
TRACES+=-at StepC=trace@0x10b/0x20 #OC5C PL5 44 ATMega2560
|
||||
|
||||
else ifeq ($(DUT),atmega168)
|
||||
DEVICE=atmega168
|
||||
TRACES+=-at StepA=trace@0x25/0x02 #OC1A PB1 9 ATMega168
|
||||
TRACES+=-at StepB=trace@0x25/0x04 #OC1B PB2 10 ATMega168
|
||||
|
||||
else ifeq ($(DUT),atmega168p)
|
||||
DEVICE=atmega168p
|
||||
TRACES+=-at StepA=trace@0x25/0x02 #OC1A PB1 9 ATMega168p
|
||||
TRACES+=-at StepB=trace@0x25/0x04 #OC1B PB2 10 ATMega168p
|
||||
|
||||
else ifeq ($(DUT),atmega328)
|
||||
DEVICE=atmega328
|
||||
TRACES+=-at StepA=trace@0x25/0x02 #OC1A PB1 9 ATMega328
|
||||
TRACES+=-at StepB=trace@0x25/0x04 #OC1B PB2 10 ATMega328
|
||||
|
||||
else ifeq ($(DUT),atmega328p)
|
||||
DEVICE=atmega328p
|
||||
TRACES+=-at StepA=trace@0x25/0x02 #OC1A PB1 9 ATMega328p
|
||||
TRACES+=-at StepB=trace@0x25/0x04 #OC1B PB2 10 ATMega328p
|
||||
|
||||
else ifeq ($(DUT),atmega32u4)
|
||||
DEVICE=atmega32u4
|
||||
TRACES+=-at StepA=trace@0x025/0x20 #OC1A PB5 11
|
||||
TRACES+=-at StepB=trace@0x025/0x40 #OC1B PB6 12
|
||||
#TRACES+=-at StepC=trace@0x025/0x80 #OC1C PB7 13
|
||||
|
||||
endif
|
||||
|
||||
ifeq ($(DEVICE),atmega2560)
|
||||
TRACES+=-at DirA=trace@0x2b/0x01 # Pin 21 PD0
|
||||
TRACES+=-at DirB=trace@0x2b/0x02 # Pin 20 PD1
|
||||
TRACES+=-at DirC=trace@0x10b/0x80 # Pin 42 PL7
|
||||
TRACES+=-at EnableA=trace@0x2b/0x04 # Pin 19 PD2
|
||||
TRACES+=-at EnableB=trace@0x2b/0x08 # Pin 18 PD3
|
||||
TRACES+=-at EnableC=trace@0x10b/0x40 # Pin 43 PL6
|
||||
|
||||
else ifeq ($(DEVICE),$(filter $(DEVICE),atmega168 atmega168p atmega328 atmega328p))
|
||||
TRACES+=-at DirA=trace@0x2b/0x20 # Pin 5 PD5
|
||||
TRACES+=-at DirB=trace@0x2b/0x80 # Pin 7 PD7
|
||||
TRACES+=-at EnableA=trace@0x2b/0x40 # Pin 6 PD6
|
||||
TRACES+=-at EnableB=trace@0x25/0x01 # Pin 8 PB0
|
||||
|
||||
else ifeq ($(DUT),atmega32u4)
|
||||
TRACES+=-at DirA=trace@0x25/0x10 # Pin 26 PB4
|
||||
TRACES+=-at DirB=trace@0x25/0x08 # Pin 14 PB3
|
||||
#TRACES+=-at DirC=trace@0x10b/0x80 # Pin 42 PL7
|
||||
TRACES+=-at EnableA=trace@0x25/0x04 # Pin 16 PB2
|
||||
TRACES+=-at EnableB=trace@0x25/0x02 # Pin 15 PB1
|
||||
#TRACES+=-at EnableC=trace@0x10b/0x40 # Pin 43 PL6
|
||||
|
||||
endif
|
||||
|
||||
FIRMWARE=".pio/build/$(DUT)/firmware.elf"
|
||||
|
||||
DIR=$(shell env pwd)
|
||||
|
||||
ifndef SILENCE
|
||||
SILENCE=0
|
||||
endif
|
||||
|
||||
test: .tested
|
||||
|
||||
.tested: result.txt expect.txt ../judge.awk
|
||||
echo DUT=$(DUT)
|
||||
rm -f .tested
|
||||
gawk -f ../judge.awk -v DIR=$(DIR) result.txt expect.txt
|
||||
test -f .tested
|
||||
|
||||
result.txt: x.vcd
|
||||
gawk -v SILENCE=$(SILENCE) -f ../eval.awk x.vcd
|
||||
cat expect.txt
|
||||
|
||||
x.vcd: $(SRC) ../run_avr platformio.ini src/ExternalCall.ino
|
||||
~/.platformio/penv/bin/pio run -e $(DUT) || ~/.local/bin/pio run -e $(DUT) || env pio run -e $(DUT)
|
||||
../run_avr $(FIRMWARE) -m $(DEVICE) -o x.vcd $(TRACES)
|
||||
|
||||
src/ExternalCall.ino:
|
||||
mkdir -p src
|
||||
cd src; ln -s ../../../../../examples/ExternalCall/ExternalCall.ino .
|
||||
|
||||
clean:
|
||||
rm -fR .pio .tested x.vcd result.txt
|
||||
22
extras/tests/simavr_based/test_externalCall/expect.txt
Normal file
22
extras/tests/simavr_based/test_externalCall/expect.txt
Normal file
@@ -0,0 +1,22 @@
|
||||
DirA: 3*L->H, 2*H->L
|
||||
DirB: 3*L->H, 2*H->L
|
||||
EnableA: 2*L->H, 1*H->L
|
||||
EnableB: 2*L->H, 1*H->L
|
||||
StepA: 2890*L->H, 2890*H->L, Max High=9us Total High=13574us
|
||||
StepB: 2890*L->H, 2890*H->L, Max High=9us Total High=13454us
|
||||
Position[A]=190
|
||||
|
||||
Position[B]=190
|
||||
|
||||
Time in DirA max=10063958 us, total=15122519 us
|
||||
|
||||
Time in DirB max=39260160 us, total=44318721 us
|
||||
|
||||
Time in EnableA max=4162 us, total=4162 us
|
||||
|
||||
Time in EnableB max=29200356 us, total=29200356 us
|
||||
|
||||
Time in StepA max=9 us, total=13574 us
|
||||
|
||||
Time in StepB max=9 us, total=13454 us
|
||||
|
||||
31
extras/tests/simavr_based/test_externalCall/platformio.ini
Normal file
31
extras/tests/simavr_based/test_externalCall/platformio.ini
Normal file
@@ -0,0 +1,31 @@
|
||||
; PlatformIO Project Configuration File
|
||||
;
|
||||
; Build options: build flags, source filter
|
||||
; Upload options: custom upload port, speed and extra flags
|
||||
; Library options: dependencies, extra library storages
|
||||
; Advanced options: extra scripting
|
||||
;
|
||||
; Please visit documentation for the other options and examples
|
||||
; https://docs.platformio.org/page/projectconf.html
|
||||
|
||||
[platformio]
|
||||
|
||||
# There should be only one env section for the DUT under test.
|
||||
# One of
|
||||
# atmega168p
|
||||
# atmega328p
|
||||
# atmega2560_timer1
|
||||
# atmega2560_timer3
|
||||
# atmega2560_timer4
|
||||
# atmega2560_timer5
|
||||
#
|
||||
[common]
|
||||
# This is the line input to StepperDemo:
|
||||
build_flags = -D SIMULATOR
|
||||
|
||||
[env:atmega328p]
|
||||
platform = atmelavr
|
||||
board = nanoatmega328
|
||||
framework = arduino
|
||||
build_flags = -Werror -Wall ${common.build_flags}
|
||||
lib_extra_dirs = ../../../../..
|
||||
1
extras/tests/simavr_based/test_issue150/.gitignore
vendored
Normal file
1
extras/tests/simavr_based/test_issue150/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
src/
|
||||
132
extras/tests/simavr_based/test_issue150/Makefile
Normal file
132
extras/tests/simavr_based/test_issue150/Makefile
Normal file
@@ -0,0 +1,132 @@
|
||||
#
|
||||
# In order to execute the test for one directory use:
|
||||
#
|
||||
# make -C test_sd_01b_328p -f ../Makefile.test
|
||||
|
||||
SRC=$(wildcard ../../../src/*) $(wildcard src/*)
|
||||
|
||||
# platformio should contain only one env section.
|
||||
# This section states the dut name
|
||||
# atmega168
|
||||
# atmega168p
|
||||
# atmega328
|
||||
# atmega328p
|
||||
# atmega2560_timer1
|
||||
# atmega2560_timer3
|
||||
# atmega2560_timer4
|
||||
# atmega2560_timer5
|
||||
#
|
||||
|
||||
DUT=$(shell gawk '/env:/{print(substr($$1,6,length($$1)-6))}' platformio.ini)
|
||||
|
||||
TRACES=-at StepISR=trace@0x25/0x08 # PB3
|
||||
TRACES+=-at FillISR=trace@0x25/0x10 # PB4
|
||||
|
||||
#
|
||||
ifeq ($(DUT),atmega2560_timer1)
|
||||
DEVICE=atmega2560
|
||||
TRACES+=-at StepA=trace@0x025/0x20 #OC1A PB5 11 ATMega2560
|
||||
TRACES+=-at StepB=trace@0x025/0x40 #OC1B PB6 12 ATMega2560
|
||||
TRACES+=-at StepC=trace@0x025/0x80 #OC1C PB7 13 ATMega2560
|
||||
#
|
||||
else ifeq ($(DUT),atmega2560_timer3)
|
||||
DEVICE=atmega2560
|
||||
TRACES+=-at StepA=trace@0x02e/0x08 #OC3A PE3 5 ATMega2560
|
||||
TRACES+=-at StepB=trace@0x02e/0x10 #OC3B PE4 2 ATMega2560
|
||||
TRACES+=-at StepC=trace@0x02e/0x20 #OC3C PE5 3 ATMega2560
|
||||
#
|
||||
else ifeq ($(DUT),atmega2560_timer4)
|
||||
DEVICE=atmega2560
|
||||
TRACES+=-at StepA=trace@0x102/0x08 #OC4A PH3 6 ATMega2560
|
||||
TRACES+=-at StepB=trace@0x102/0x10 #OC4B PH4 7 ATMega2560
|
||||
TRACES+=-at StepC=trace@0x102/0x20 #OC4C PH5 8 ATMega2560
|
||||
#
|
||||
else ifeq ($(DUT),atmega2560_timer5)
|
||||
DEVICE=atmega2560
|
||||
TRACES+=-at StepA=trace@0x10b/0x08 #OC5A PL3 46 ATMega2560
|
||||
TRACES+=-at StepB=trace@0x10b/0x10 #OC5B PL4 45 ATMega2560
|
||||
TRACES+=-at StepC=trace@0x10b/0x20 #OC5C PL5 44 ATMega2560
|
||||
|
||||
else ifeq ($(DUT),atmega168)
|
||||
DEVICE=atmega168
|
||||
TRACES+=-at StepA=trace@0x25/0x02 #OC1A PB1 9 atmega168
|
||||
TRACES+=-at StepB=trace@0x25/0x04 #OC1B PB2 10 atmega168
|
||||
|
||||
else ifeq ($(DUT),atmega168p)
|
||||
DEVICE=atmega168p
|
||||
TRACES+=-at StepA=trace@0x25/0x02 #OC1A PB1 9 atmega168p
|
||||
TRACES+=-at StepB=trace@0x25/0x04 #OC1B PB2 10 atmega168p
|
||||
|
||||
else ifeq ($(DUT),atmega328)
|
||||
DEVICE=atmega328
|
||||
TRACES+=-at StepA=trace@0x25/0x02 #OC1A PB1 9 ATMega328
|
||||
TRACES+=-at StepB=trace@0x25/0x04 #OC1B PB2 10 ATMega328
|
||||
|
||||
else ifeq ($(DUT),atmega328p)
|
||||
DEVICE=atmega328p
|
||||
TRACES+=-at StepA=trace@0x25/0x02 #OC1A PB1 9 ATMega328p
|
||||
TRACES+=-at StepB=trace@0x25/0x04 #OC1B PB2 10 ATMega328p
|
||||
|
||||
else ifeq ($(DUT),atmega32u4)
|
||||
DEVICE=atmega32u4
|
||||
TRACES+=-at StepA=trace@0x025/0x20 #OC1A PB5 11
|
||||
TRACES+=-at StepB=trace@0x025/0x40 #OC1B PB6 12
|
||||
#TRACES+=-at StepC=trace@0x025/0x80 #OC1C PB7 13
|
||||
|
||||
endif
|
||||
|
||||
ifeq ($(DEVICE),atmega2560)
|
||||
TRACES+=-at DirA=trace@0x2b/0x01 # Pin 21 PD0
|
||||
TRACES+=-at DirB=trace@0x2b/0x02 # Pin 20 PD1
|
||||
TRACES+=-at DirC=trace@0x10b/0x80 # Pin 42 PL7
|
||||
TRACES+=-at EnableA=trace@0x2b/0x04 # Pin 19 PD2
|
||||
TRACES+=-at EnableB=trace@0x2b/0x08 # Pin 18 PD3
|
||||
TRACES+=-at EnableC=trace@0x10b/0x40 # Pin 43 PL6
|
||||
|
||||
else ifeq ($(DEVICE),$(filter $(DEVICE),atmega168 atmega168p atmega328 atmega328p))
|
||||
TRACES+=-at DirA=trace@0x2b/0x20 # Pin 5 PD5
|
||||
TRACES+=-at DirB=trace@0x2b/0x80 # Pin 7 PD7
|
||||
TRACES+=-at EnableA=trace@0x2b/0x40 # Pin 6 PD6
|
||||
TRACES+=-at EnableB=trace@0x25/0x01 # Pin 8 PB0
|
||||
|
||||
else ifeq ($(DUT),atmega32u4)
|
||||
TRACES+=-at DirA=trace@0x25/0x10 # Pin 26 PB4
|
||||
TRACES+=-at DirB=trace@0x25/0x08 # Pin 14 PB3
|
||||
#TRACES+=-at DirC=trace@0x10b/0x80 # Pin 42 PL7
|
||||
TRACES+=-at EnableA=trace@0x25/0x04 # Pin 16 PB2
|
||||
TRACES+=-at EnableB=trace@0x25/0x02 # Pin 15 PB1
|
||||
#TRACES+=-at EnableC=trace@0x10b/0x40 # Pin 43 PL6
|
||||
|
||||
endif
|
||||
|
||||
FIRMWARE=".pio/build/$(DUT)/firmware.elf"
|
||||
|
||||
DIR=$(shell env pwd)
|
||||
|
||||
ifndef SILENCE
|
||||
SILENCE=0
|
||||
endif
|
||||
|
||||
test: .tested
|
||||
|
||||
.tested: result.txt expect.txt ../judge.awk
|
||||
echo DUT=$(DUT)
|
||||
rm -f .tested
|
||||
gawk -f ../judge.awk -v DIR=$(DIR) result.txt expect.txt
|
||||
test -f .tested
|
||||
|
||||
result.txt: x.vcd
|
||||
gawk -v SILENCE=$(SILENCE) -f ../eval.awk x.vcd >/dev/null
|
||||
cat expect.txt
|
||||
|
||||
x.vcd: $(SRC) ../run_avr platformio.ini src/Issue150.ino
|
||||
~/.platformio/penv/bin/pio run -e $(DUT) || ~/.local/bin/pio run -e $(DUT) || env pio run -e $(DUT)
|
||||
../run_avr $(FIRMWARE) -m $(DEVICE) -o x.vcd $(TRACES)
|
||||
|
||||
src/Issue150.ino:
|
||||
mkdir -p src
|
||||
cd src; ln -s ../../../../../examples/Issue150/Issue150.ino .
|
||||
|
||||
clean:
|
||||
rm -fR .pio .tested x.vcd result.txt
|
||||
|
||||
16
extras/tests/simavr_based/test_issue150/expect.txt
Normal file
16
extras/tests/simavr_based/test_issue150/expect.txt
Normal file
@@ -0,0 +1,16 @@
|
||||
DirA: 0*L->H, 0*H->L
|
||||
DirB: 1*L->H, 0*H->L
|
||||
EnableA: 2*L->H, 1*H->L
|
||||
EnableB: 0*L->H, 0*H->L
|
||||
StepA: 4000*L->H, 4000*H->L, Max High=10us Total High=20775us
|
||||
StepB: 2*L->H, 2*H->L, Max High=4us Total High=9us
|
||||
Position[A]=4000
|
||||
|
||||
Position[B]=2
|
||||
|
||||
Time in EnableA max=4194 us, total=4194 us
|
||||
|
||||
Time in StepA max=10 us, total=20775 us
|
||||
|
||||
Time in StepB max=4 us, total=9 us
|
||||
|
||||
31
extras/tests/simavr_based/test_issue150/platformio.ini
Normal file
31
extras/tests/simavr_based/test_issue150/platformio.ini
Normal file
@@ -0,0 +1,31 @@
|
||||
; PlatformIO Project Configuration File
|
||||
;
|
||||
; Build options: build flags, source filter
|
||||
; Upload options: custom upload port, speed and extra flags
|
||||
; Library options: dependencies, extra library storages
|
||||
; Advanced options: extra scripting
|
||||
;
|
||||
; Please visit documentation for the other options and examples
|
||||
; https://docs.platformio.org/page/projectconf.html
|
||||
|
||||
[platformio]
|
||||
|
||||
# There should be only one env section for the DUT under test.
|
||||
# One of
|
||||
# atmega168p
|
||||
# atmega328p
|
||||
# atmega2560_timer1
|
||||
# atmega2560_timer3
|
||||
# atmega2560_timer4
|
||||
# atmega2560_timer5
|
||||
#
|
||||
[common]
|
||||
# This is the line input to StepperDemo:
|
||||
build_flags = -D SIMULATOR
|
||||
|
||||
[env:atmega328p]
|
||||
platform = atmelavr
|
||||
board = nanoatmega328
|
||||
framework = arduino
|
||||
build_flags = -Werror -Wall ${common.build_flags}
|
||||
lib_extra_dirs = ../../../../..
|
||||
1
extras/tests/simavr_based/test_issue151/.gitignore
vendored
Normal file
1
extras/tests/simavr_based/test_issue151/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
src/
|
||||
132
extras/tests/simavr_based/test_issue151/Makefile
Normal file
132
extras/tests/simavr_based/test_issue151/Makefile
Normal file
@@ -0,0 +1,132 @@
|
||||
#
|
||||
# In order to execute the test for one directory use:
|
||||
#
|
||||
# make -C test_sd_01b_328p -f ../Makefile.test
|
||||
|
||||
SRC=$(wildcard ../../../src/*) $(wildcard src/*)
|
||||
|
||||
# platformio should contain only one env section.
|
||||
# This section states the dut name
|
||||
# atmega168
|
||||
# atmega168p
|
||||
# atmega328
|
||||
# atmega328p
|
||||
# atmega2560_timer1
|
||||
# atmega2560_timer3
|
||||
# atmega2560_timer4
|
||||
# atmega2560_timer5
|
||||
#
|
||||
|
||||
DUT=$(shell gawk '/env:/{print(substr($$1,6,length($$1)-6))}' platformio.ini)
|
||||
|
||||
TRACES=-at StepISR=trace@0x25/0x08 # PB3
|
||||
TRACES+=-at FillISR=trace@0x25/0x10 # PB4
|
||||
|
||||
#
|
||||
ifeq ($(DUT),atmega2560_timer1)
|
||||
DEVICE=atmega2560
|
||||
TRACES+=-at StepA=trace@0x025/0x20 #OC1A PB5 11 ATMega2560
|
||||
TRACES+=-at StepB=trace@0x025/0x40 #OC1B PB6 12 ATMega2560
|
||||
TRACES+=-at StepC=trace@0x025/0x80 #OC1C PB7 13 ATMega2560
|
||||
#
|
||||
else ifeq ($(DUT),atmega2560_timer3)
|
||||
DEVICE=atmega2560
|
||||
TRACES+=-at StepA=trace@0x02e/0x08 #OC3A PE3 5 ATMega2560
|
||||
TRACES+=-at StepB=trace@0x02e/0x10 #OC3B PE4 2 ATMega2560
|
||||
TRACES+=-at StepC=trace@0x02e/0x20 #OC3C PE5 3 ATMega2560
|
||||
#
|
||||
else ifeq ($(DUT),atmega2560_timer4)
|
||||
DEVICE=atmega2560
|
||||
TRACES+=-at StepA=trace@0x102/0x08 #OC4A PH3 6 ATMega2560
|
||||
TRACES+=-at StepB=trace@0x102/0x10 #OC4B PH4 7 ATMega2560
|
||||
TRACES+=-at StepC=trace@0x102/0x20 #OC4C PH5 8 ATMega2560
|
||||
#
|
||||
else ifeq ($(DUT),atmega2560_timer5)
|
||||
DEVICE=atmega2560
|
||||
TRACES+=-at StepA=trace@0x10b/0x08 #OC5A PL3 46 ATMega2560
|
||||
TRACES+=-at StepB=trace@0x10b/0x10 #OC5B PL4 45 ATMega2560
|
||||
TRACES+=-at StepC=trace@0x10b/0x20 #OC5C PL5 44 ATMega2560
|
||||
|
||||
else ifeq ($(DUT),atmega168)
|
||||
DEVICE=atmega168
|
||||
TRACES+=-at StepA=trace@0x25/0x02 #OC1A PB1 9 atmega168
|
||||
TRACES+=-at StepB=trace@0x25/0x04 #OC1B PB2 10 atmega168
|
||||
|
||||
else ifeq ($(DUT),atmega168p)
|
||||
DEVICE=atmega168p
|
||||
TRACES+=-at StepA=trace@0x25/0x02 #OC1A PB1 9 atmega168p
|
||||
TRACES+=-at StepB=trace@0x25/0x04 #OC1B PB2 10 atmega168p
|
||||
|
||||
else ifeq ($(DUT),atmega328)
|
||||
DEVICE=atmega328
|
||||
TRACES+=-at StepA=trace@0x25/0x02 #OC1A PB1 9 ATMega328
|
||||
TRACES+=-at StepB=trace@0x25/0x04 #OC1B PB2 10 ATMega328
|
||||
|
||||
else ifeq ($(DUT),atmega328p)
|
||||
DEVICE=atmega328p
|
||||
TRACES+=-at StepA=trace@0x25/0x02 #OC1A PB1 9 ATMega328p
|
||||
TRACES+=-at StepB=trace@0x25/0x04 #OC1B PB2 10 ATMega328p
|
||||
|
||||
else ifeq ($(DUT),atmega32u4)
|
||||
DEVICE=atmega32u4
|
||||
TRACES+=-at StepA=trace@0x025/0x20 #OC1A PB5 11
|
||||
TRACES+=-at StepB=trace@0x025/0x40 #OC1B PB6 12
|
||||
#TRACES+=-at StepC=trace@0x025/0x80 #OC1C PB7 13
|
||||
|
||||
endif
|
||||
|
||||
ifeq ($(DEVICE),atmega2560)
|
||||
TRACES+=-at DirA=trace@0x2b/0x01 # Pin 21 PD0
|
||||
TRACES+=-at DirB=trace@0x2b/0x02 # Pin 20 PD1
|
||||
TRACES+=-at DirC=trace@0x10b/0x80 # Pin 42 PL7
|
||||
TRACES+=-at EnableA=trace@0x2b/0x04 # Pin 19 PD2
|
||||
TRACES+=-at EnableB=trace@0x2b/0x08 # Pin 18 PD3
|
||||
TRACES+=-at EnableC=trace@0x10b/0x40 # Pin 43 PL6
|
||||
|
||||
else ifeq ($(DEVICE),$(filter $(DEVICE),atmega168 atmega168p atmega328 atmega328p))
|
||||
TRACES+=-at DirA=trace@0x2b/0x20 # Pin 5 PD5
|
||||
TRACES+=-at DirB=trace@0x2b/0x80 # Pin 7 PD7
|
||||
TRACES+=-at EnableA=trace@0x2b/0x40 # Pin 6 PD6
|
||||
TRACES+=-at EnableB=trace@0x25/0x01 # Pin 8 PB0
|
||||
|
||||
else ifeq ($(DUT),atmega32u4)
|
||||
TRACES+=-at DirA=trace@0x25/0x10 # Pin 26 PB4
|
||||
TRACES+=-at DirB=trace@0x25/0x08 # Pin 14 PB3
|
||||
#TRACES+=-at DirC=trace@0x10b/0x80 # Pin 42 PL7
|
||||
TRACES+=-at EnableA=trace@0x25/0x04 # Pin 16 PB2
|
||||
TRACES+=-at EnableB=trace@0x25/0x02 # Pin 15 PB1
|
||||
#TRACES+=-at EnableC=trace@0x10b/0x40 # Pin 43 PL6
|
||||
|
||||
endif
|
||||
|
||||
FIRMWARE=".pio/build/$(DUT)/firmware.elf"
|
||||
|
||||
DIR=$(shell env pwd)
|
||||
|
||||
ifndef SILENCE
|
||||
SILENCE=0
|
||||
endif
|
||||
|
||||
test: .tested
|
||||
|
||||
.tested: result.txt expect.txt ../judge.awk
|
||||
echo DUT=$(DUT)
|
||||
rm -f .tested
|
||||
gawk -f ../judge.awk -v DIR=$(DIR) result.txt expect.txt
|
||||
test -f .tested
|
||||
|
||||
result.txt: x.vcd
|
||||
gawk -v SILENCE=$(SILENCE) -f ../eval.awk x.vcd >/dev/null
|
||||
cat expect.txt
|
||||
|
||||
x.vcd: $(SRC) ../run_avr platformio.ini src/Issue151.ino
|
||||
~/.platformio/penv/bin/pio run -e $(DUT) || ~/.local/bin/pio run -e $(DUT) || env pio run -e $(DUT)
|
||||
../run_avr $(FIRMWARE) -m $(DEVICE) -o x.vcd $(TRACES)
|
||||
|
||||
src/Issue151.ino:
|
||||
mkdir -p src
|
||||
cd src; ln -s ../../../../../examples/Issue151/Issue151.ino .
|
||||
|
||||
clean:
|
||||
rm -fR .pio .tested x.vcd result.txt
|
||||
|
||||
16
extras/tests/simavr_based/test_issue151/expect.txt
Normal file
16
extras/tests/simavr_based/test_issue151/expect.txt
Normal file
@@ -0,0 +1,16 @@
|
||||
DirA: 0*L->H, 0*H->L
|
||||
DirB: 1*L->H, 0*H->L
|
||||
EnableA: 2*L->H, 1*H->L
|
||||
EnableB: 0*L->H, 0*H->L
|
||||
StepA: 20000*L->H, 20000*H->L, Max High=10us Total High=101913us
|
||||
StepB: 2*L->H, 2*H->L, Max High=4us Total High=9us
|
||||
Position[A]=20000
|
||||
|
||||
Position[B]=2
|
||||
|
||||
Time in EnableA max=4203 us, total=4203 us
|
||||
|
||||
Time in StepA max=10 us, total=101913 us
|
||||
|
||||
Time in StepB max=4 us, total=9 us
|
||||
|
||||
31
extras/tests/simavr_based/test_issue151/platformio.ini
Normal file
31
extras/tests/simavr_based/test_issue151/platformio.ini
Normal file
@@ -0,0 +1,31 @@
|
||||
; PlatformIO Project Configuration File
|
||||
;
|
||||
; Build options: build flags, source filter
|
||||
; Upload options: custom upload port, speed and extra flags
|
||||
; Library options: dependencies, extra library storages
|
||||
; Advanced options: extra scripting
|
||||
;
|
||||
; Please visit documentation for the other options and examples
|
||||
; https://docs.platformio.org/page/projectconf.html
|
||||
|
||||
[platformio]
|
||||
|
||||
# There should be only one env section for the DUT under test.
|
||||
# One of
|
||||
# atmega168p
|
||||
# atmega328p
|
||||
# atmega2560_timer1
|
||||
# atmega2560_timer3
|
||||
# atmega2560_timer4
|
||||
# atmega2560_timer5
|
||||
#
|
||||
[common]
|
||||
# This is the line input to StepperDemo:
|
||||
build_flags = -D SIMULATOR
|
||||
|
||||
[env:atmega328p]
|
||||
platform = atmelavr
|
||||
board = nanoatmega328
|
||||
framework = arduino
|
||||
build_flags = -Werror -Wall ${common.build_flags}
|
||||
lib_extra_dirs = ../../../../..
|
||||
1
extras/tests/simavr_based/test_issue152/.gitignore
vendored
Normal file
1
extras/tests/simavr_based/test_issue152/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
src/
|
||||
132
extras/tests/simavr_based/test_issue152/Makefile
Normal file
132
extras/tests/simavr_based/test_issue152/Makefile
Normal file
@@ -0,0 +1,132 @@
|
||||
#
|
||||
# In order to execute the test for one directory use:
|
||||
#
|
||||
# make -C test_sd_01b_328p -f ../Makefile.test
|
||||
|
||||
SRC=$(wildcard ../../../src/*) $(wildcard src/*)
|
||||
|
||||
# platformio should contain only one env section.
|
||||
# This section states the dut name
|
||||
# atmega168
|
||||
# atmega168p
|
||||
# atmega328
|
||||
# atmega328p
|
||||
# atmega2560_timer1
|
||||
# atmega2560_timer3
|
||||
# atmega2560_timer4
|
||||
# atmega2560_timer5
|
||||
#
|
||||
|
||||
DUT=$(shell gawk '/env:/{print(substr($$1,6,length($$1)-6))}' platformio.ini)
|
||||
|
||||
TRACES=-at StepISR=trace@0x25/0x08 # PB3
|
||||
TRACES+=-at FillISR=trace@0x25/0x10 # PB4
|
||||
|
||||
#
|
||||
ifeq ($(DUT),atmega2560_timer1)
|
||||
DEVICE=atmega2560
|
||||
TRACES+=-at StepA=trace@0x025/0x20 #OC1A PB5 11 ATMega2560
|
||||
TRACES+=-at StepB=trace@0x025/0x40 #OC1B PB6 12 ATMega2560
|
||||
TRACES+=-at StepC=trace@0x025/0x80 #OC1C PB7 13 ATMega2560
|
||||
#
|
||||
else ifeq ($(DUT),atmega2560_timer3)
|
||||
DEVICE=atmega2560
|
||||
TRACES+=-at StepA=trace@0x02e/0x08 #OC3A PE3 5 ATMega2560
|
||||
TRACES+=-at StepB=trace@0x02e/0x10 #OC3B PE4 2 ATMega2560
|
||||
TRACES+=-at StepC=trace@0x02e/0x20 #OC3C PE5 3 ATMega2560
|
||||
#
|
||||
else ifeq ($(DUT),atmega2560_timer4)
|
||||
DEVICE=atmega2560
|
||||
TRACES+=-at StepA=trace@0x102/0x08 #OC4A PH3 6 ATMega2560
|
||||
TRACES+=-at StepB=trace@0x102/0x10 #OC4B PH4 7 ATMega2560
|
||||
TRACES+=-at StepC=trace@0x102/0x20 #OC4C PH5 8 ATMega2560
|
||||
#
|
||||
else ifeq ($(DUT),atmega2560_timer5)
|
||||
DEVICE=atmega2560
|
||||
TRACES+=-at StepA=trace@0x10b/0x08 #OC5A PL3 46 ATMega2560
|
||||
TRACES+=-at StepB=trace@0x10b/0x10 #OC5B PL4 45 ATMega2560
|
||||
TRACES+=-at StepC=trace@0x10b/0x20 #OC5C PL5 44 ATMega2560
|
||||
|
||||
else ifeq ($(DUT),atmega168)
|
||||
DEVICE=atmega168
|
||||
TRACES+=-at StepA=trace@0x25/0x02 #OC1A PB1 9 atmega168
|
||||
TRACES+=-at StepB=trace@0x25/0x04 #OC1B PB2 10 atmega168
|
||||
|
||||
else ifeq ($(DUT),atmega168p)
|
||||
DEVICE=atmega168p
|
||||
TRACES+=-at StepA=trace@0x25/0x02 #OC1A PB1 9 atmega168p
|
||||
TRACES+=-at StepB=trace@0x25/0x04 #OC1B PB2 10 atmega168p
|
||||
|
||||
else ifeq ($(DUT),atmega328)
|
||||
DEVICE=atmega328
|
||||
TRACES+=-at StepA=trace@0x25/0x02 #OC1A PB1 9 ATMega328
|
||||
TRACES+=-at StepB=trace@0x25/0x04 #OC1B PB2 10 ATMega328
|
||||
|
||||
else ifeq ($(DUT),atmega328p)
|
||||
DEVICE=atmega328p
|
||||
TRACES+=-at StepA=trace@0x25/0x02 #OC1A PB1 9 ATMega328p
|
||||
TRACES+=-at StepB=trace@0x25/0x04 #OC1B PB2 10 ATMega328p
|
||||
|
||||
else ifeq ($(DUT),atmega32u4)
|
||||
DEVICE=atmega32u4
|
||||
TRACES+=-at StepA=trace@0x025/0x20 #OC1A PB5 11
|
||||
TRACES+=-at StepB=trace@0x025/0x40 #OC1B PB6 12
|
||||
#TRACES+=-at StepC=trace@0x025/0x80 #OC1C PB7 13
|
||||
|
||||
endif
|
||||
|
||||
ifeq ($(DEVICE),atmega2560)
|
||||
TRACES+=-at DirA=trace@0x2b/0x01 # Pin 21 PD0
|
||||
TRACES+=-at DirB=trace@0x2b/0x02 # Pin 20 PD1
|
||||
TRACES+=-at DirC=trace@0x10b/0x80 # Pin 42 PL7
|
||||
TRACES+=-at EnableA=trace@0x2b/0x04 # Pin 19 PD2
|
||||
TRACES+=-at EnableB=trace@0x2b/0x08 # Pin 18 PD3
|
||||
TRACES+=-at EnableC=trace@0x10b/0x40 # Pin 43 PL6
|
||||
|
||||
else ifeq ($(DEVICE),$(filter $(DEVICE),atmega168 atmega168p atmega328 atmega328p))
|
||||
TRACES+=-at DirA=trace@0x2b/0x20 # Pin 5 PD5
|
||||
TRACES+=-at DirB=trace@0x2b/0x80 # Pin 7 PD7
|
||||
TRACES+=-at EnableA=trace@0x2b/0x40 # Pin 6 PD6
|
||||
TRACES+=-at EnableB=trace@0x25/0x01 # Pin 8 PB0
|
||||
|
||||
else ifeq ($(DUT),atmega32u4)
|
||||
TRACES+=-at DirA=trace@0x25/0x10 # Pin 26 PB4
|
||||
TRACES+=-at DirB=trace@0x25/0x08 # Pin 14 PB3
|
||||
#TRACES+=-at DirC=trace@0x10b/0x80 # Pin 42 PL7
|
||||
TRACES+=-at EnableA=trace@0x25/0x04 # Pin 16 PB2
|
||||
TRACES+=-at EnableB=trace@0x25/0x02 # Pin 15 PB1
|
||||
#TRACES+=-at EnableC=trace@0x10b/0x40 # Pin 43 PL6
|
||||
|
||||
endif
|
||||
|
||||
FIRMWARE=".pio/build/$(DUT)/firmware.elf"
|
||||
|
||||
DIR=$(shell env pwd)
|
||||
|
||||
ifndef SILENCE
|
||||
SILENCE=0
|
||||
endif
|
||||
|
||||
test: .tested
|
||||
|
||||
.tested: result.txt expect.txt ../judge.awk
|
||||
echo DUT=$(DUT)
|
||||
rm -f .tested
|
||||
gawk -f ../judge.awk -v DIR=$(DIR) result.txt expect.txt
|
||||
test -f .tested
|
||||
|
||||
result.txt: x.vcd
|
||||
gawk -v SILENCE=$(SILENCE) -f ../eval.awk x.vcd >/dev/null
|
||||
cat expect.txt
|
||||
|
||||
x.vcd: $(SRC) ../run_avr platformio.ini src/Issue152.ino
|
||||
~/.platformio/penv/bin/pio run -e $(DUT) || ~/.local/bin/pio run -e $(DUT) || env pio run -e $(DUT)
|
||||
../run_avr $(FIRMWARE) -m $(DEVICE) -o x.vcd $(TRACES)
|
||||
|
||||
src/Issue152.ino:
|
||||
mkdir -p src
|
||||
cd src; ln -s ../../../../../examples/Issue152/Issue152.ino .
|
||||
|
||||
clean:
|
||||
rm -fR .pio .tested x.vcd result.txt
|
||||
|
||||
20
extras/tests/simavr_based/test_issue152/expect.txt
Normal file
20
extras/tests/simavr_based/test_issue152/expect.txt
Normal file
@@ -0,0 +1,20 @@
|
||||
DirA: 0*L->H, 0*H->L
|
||||
DirB: 1*L->H, 0*H->L
|
||||
EnableA: 2*L->H, 1*H->L
|
||||
EnableB: 0*L->H, 0*H->L
|
||||
StepA: 20000*L->H, 20000*H->L, Max High=10us Total High=104644us
|
||||
StepB: 2*L->H, 2*H->L, Max High=4us Total High=9us
|
||||
Position[A]=20000
|
||||
|
||||
Position[B]=2
|
||||
|
||||
Time in EnableA max=4199 us, total=4199 us
|
||||
|
||||
Time in FillISR max=1848 us, total=59230 us
|
||||
|
||||
Time in StepA max=10 us, total=104644 us
|
||||
|
||||
Time in StepB max=4 us, total=9 us
|
||||
|
||||
Time in StepISR max=7 us, total=85706 us
|
||||
|
||||
31
extras/tests/simavr_based/test_issue152/platformio.ini
Normal file
31
extras/tests/simavr_based/test_issue152/platformio.ini
Normal file
@@ -0,0 +1,31 @@
|
||||
; PlatformIO Project Configuration File
|
||||
;
|
||||
; Build options: build flags, source filter
|
||||
; Upload options: custom upload port, speed and extra flags
|
||||
; Library options: dependencies, extra library storages
|
||||
; Advanced options: extra scripting
|
||||
;
|
||||
; Please visit documentation for the other options and examples
|
||||
; https://docs.platformio.org/page/projectconf.html
|
||||
|
||||
[platformio]
|
||||
|
||||
# There should be only one env section for the DUT under test.
|
||||
# One of
|
||||
# atmega168p
|
||||
# atmega328p
|
||||
# atmega2560_timer1
|
||||
# atmega2560_timer3
|
||||
# atmega2560_timer4
|
||||
# atmega2560_timer5
|
||||
#
|
||||
[common]
|
||||
# This is the line input to StepperDemo:
|
||||
build_flags = -D SIMULATOR -D SIMAVR_TIME_MEASUREMENT
|
||||
|
||||
[env:atmega328p]
|
||||
platform = atmelavr
|
||||
board = nanoatmega328
|
||||
framework = arduino
|
||||
build_flags = -Werror -Wall ${common.build_flags}
|
||||
lib_extra_dirs = ../../../../..
|
||||
1
extras/tests/simavr_based/test_issue172/.gitignore
vendored
Normal file
1
extras/tests/simavr_based/test_issue172/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
src/
|
||||
132
extras/tests/simavr_based/test_issue172/Makefile
Normal file
132
extras/tests/simavr_based/test_issue172/Makefile
Normal file
@@ -0,0 +1,132 @@
|
||||
#
|
||||
# In order to execute the test for one directory use:
|
||||
#
|
||||
# make -C test_sd_01b_328p -f ../Makefile.test
|
||||
|
||||
SRC=$(wildcard ../../../src/*) $(wildcard src/*)
|
||||
|
||||
# platformio should contain only one env section.
|
||||
# This section states the dut name
|
||||
# atmega168
|
||||
# atmega168p
|
||||
# atmega328
|
||||
# atmega328p
|
||||
# atmega2560_timer1
|
||||
# atmega2560_timer3
|
||||
# atmega2560_timer4
|
||||
# atmega2560_timer5
|
||||
#
|
||||
|
||||
DUT=$(shell gawk '/env:/{print(substr($$1,6,length($$1)-6))}' platformio.ini)
|
||||
|
||||
TRACES=-at StepISR=trace@0x25/0x08 # PB3
|
||||
TRACES+=-at FillISR=trace@0x25/0x10 # PB4
|
||||
|
||||
#
|
||||
ifeq ($(DUT),atmega2560_timer1)
|
||||
DEVICE=atmega2560
|
||||
TRACES+=-at StepA=trace@0x025/0x20 #OC1A PB5 11 ATMega2560
|
||||
TRACES+=-at StepB=trace@0x025/0x40 #OC1B PB6 12 ATMega2560
|
||||
TRACES+=-at StepC=trace@0x025/0x80 #OC1C PB7 13 ATMega2560
|
||||
#
|
||||
else ifeq ($(DUT),atmega2560_timer3)
|
||||
DEVICE=atmega2560
|
||||
TRACES+=-at StepA=trace@0x02e/0x08 #OC3A PE3 5 ATMega2560
|
||||
TRACES+=-at StepB=trace@0x02e/0x10 #OC3B PE4 2 ATMega2560
|
||||
TRACES+=-at StepC=trace@0x02e/0x20 #OC3C PE5 3 ATMega2560
|
||||
#
|
||||
else ifeq ($(DUT),atmega2560_timer4)
|
||||
DEVICE=atmega2560
|
||||
TRACES+=-at StepA=trace@0x102/0x08 #OC4A PH3 6 ATMega2560
|
||||
TRACES+=-at StepB=trace@0x102/0x10 #OC4B PH4 7 ATMega2560
|
||||
TRACES+=-at StepC=trace@0x102/0x20 #OC4C PH5 8 ATMega2560
|
||||
#
|
||||
else ifeq ($(DUT),atmega2560_timer5)
|
||||
DEVICE=atmega2560
|
||||
TRACES+=-at StepA=trace@0x10b/0x08 #OC5A PL3 46 ATMega2560
|
||||
TRACES+=-at StepB=trace@0x10b/0x10 #OC5B PL4 45 ATMega2560
|
||||
TRACES+=-at StepC=trace@0x10b/0x20 #OC5C PL5 44 ATMega2560
|
||||
|
||||
else ifeq ($(DUT),atmega168)
|
||||
DEVICE=atmega168
|
||||
TRACES+=-at StepA=trace@0x25/0x02 #OC1A PB1 9 atmega168
|
||||
TRACES+=-at StepB=trace@0x25/0x04 #OC1B PB2 10 atmega168
|
||||
|
||||
else ifeq ($(DUT),atmega168p)
|
||||
DEVICE=atmega168p
|
||||
TRACES+=-at StepA=trace@0x25/0x02 #OC1A PB1 9 atmega168p
|
||||
TRACES+=-at StepB=trace@0x25/0x04 #OC1B PB2 10 atmega168p
|
||||
|
||||
else ifeq ($(DUT),atmega328)
|
||||
DEVICE=atmega328
|
||||
TRACES+=-at StepA=trace@0x25/0x02 #OC1A PB1 9 ATMega328
|
||||
TRACES+=-at StepB=trace@0x25/0x04 #OC1B PB2 10 ATMega328
|
||||
|
||||
else ifeq ($(DUT),atmega328p)
|
||||
DEVICE=atmega328p
|
||||
TRACES+=-at StepA=trace@0x25/0x02 #OC1A PB1 9 ATMega328p
|
||||
TRACES+=-at StepB=trace@0x25/0x04 #OC1B PB2 10 ATMega328p
|
||||
|
||||
else ifeq ($(DUT),atmega32u4)
|
||||
DEVICE=atmega32u4
|
||||
TRACES+=-at StepA=trace@0x025/0x20 #OC1A PB5 11
|
||||
TRACES+=-at StepB=trace@0x025/0x40 #OC1B PB6 12
|
||||
#TRACES+=-at StepC=trace@0x025/0x80 #OC1C PB7 13
|
||||
|
||||
endif
|
||||
|
||||
ifeq ($(DEVICE),atmega2560)
|
||||
TRACES+=-at DirA=trace@0x2b/0x01 # Pin 21 PD0
|
||||
TRACES+=-at DirB=trace@0x2b/0x02 # Pin 20 PD1
|
||||
TRACES+=-at DirC=trace@0x10b/0x80 # Pin 42 PL7
|
||||
TRACES+=-at EnableA=trace@0x2b/0x04 # Pin 19 PD2
|
||||
TRACES+=-at EnableB=trace@0x2b/0x08 # Pin 18 PD3
|
||||
TRACES+=-at EnableC=trace@0x10b/0x40 # Pin 43 PL6
|
||||
|
||||
else ifeq ($(DEVICE),$(filter $(DEVICE),atmega168 atmega168p atmega328 atmega328p))
|
||||
TRACES+=-at DirA=trace@0x2b/0x20 # Pin 5 PD5
|
||||
TRACES+=-at DirB=trace@0x2b/0x80 # Pin 7 PD7
|
||||
TRACES+=-at EnableA=trace@0x2b/0x40 # Pin 6 PD6
|
||||
TRACES+=-at EnableB=trace@0x25/0x01 # Pin 8 PB0
|
||||
|
||||
else ifeq ($(DUT),atmega32u4)
|
||||
TRACES+=-at DirA=trace@0x25/0x10 # Pin 26 PB4
|
||||
TRACES+=-at DirB=trace@0x25/0x08 # Pin 14 PB3
|
||||
#TRACES+=-at DirC=trace@0x10b/0x80 # Pin 42 PL7
|
||||
TRACES+=-at EnableA=trace@0x25/0x04 # Pin 16 PB2
|
||||
TRACES+=-at EnableB=trace@0x25/0x02 # Pin 15 PB1
|
||||
#TRACES+=-at EnableC=trace@0x10b/0x40 # Pin 43 PL6
|
||||
|
||||
endif
|
||||
|
||||
FIRMWARE=".pio/build/$(DUT)/firmware.elf"
|
||||
|
||||
DIR=$(shell env pwd)
|
||||
|
||||
ifndef SILENCE
|
||||
SILENCE=0
|
||||
endif
|
||||
|
||||
test: .tested
|
||||
|
||||
.tested: result.txt expect.txt ../judge.awk
|
||||
echo DUT=$(DUT)
|
||||
rm -f .tested
|
||||
gawk -f ../judge.awk -v DIR=$(DIR) result.txt expect.txt
|
||||
test -f .tested
|
||||
|
||||
result.txt: x.vcd
|
||||
gawk -v SILENCE=$(SILENCE) -f ../eval.awk x.vcd >/dev/null
|
||||
cat expect.txt
|
||||
|
||||
x.vcd: $(SRC) ../run_avr platformio.ini src/Issue172.ino
|
||||
~/.platformio/penv/bin/pio run -e $(DUT) || ~/.local/bin/pio run -e $(DUT) || env pio run -e $(DUT)
|
||||
../run_avr $(FIRMWARE) -m $(DEVICE) -o x.vcd $(TRACES)
|
||||
|
||||
src/Issue172.ino:
|
||||
mkdir -p src
|
||||
cd src; ln -s ../../../../../examples/Issue172/Issue172.ino .
|
||||
|
||||
clean:
|
||||
rm -fR .pio .tested x.vcd result.txt
|
||||
|
||||
20
extras/tests/simavr_based/test_issue172/expect.txt
Normal file
20
extras/tests/simavr_based/test_issue172/expect.txt
Normal file
@@ -0,0 +1,20 @@
|
||||
DirA: 0*L->H, 1*H->L
|
||||
DirB: 1*L->H, 0*H->L
|
||||
EnableA: 2*L->H, 1*H->L
|
||||
EnableB: 0*L->H, 0*H->L
|
||||
StepA: 2060*L->H, 2060*H->L, Max High=9us Total High=8067us
|
||||
StepB: 2*L->H, 2*H->L, Max High=4us Total High=9us
|
||||
Position[A]=0
|
||||
|
||||
Position[B]=2
|
||||
|
||||
Time in EnableA max=4204 us, total=4204 us
|
||||
|
||||
Time in FillISR max=1737 us, total=39497 us
|
||||
|
||||
Time in StepA max=9 us, total=8067 us
|
||||
|
||||
Time in StepB max=4 us, total=9 us
|
||||
|
||||
Time in StepISR max=6 us, total=8184 us
|
||||
|
||||
31
extras/tests/simavr_based/test_issue172/platformio.ini
Normal file
31
extras/tests/simavr_based/test_issue172/platformio.ini
Normal file
@@ -0,0 +1,31 @@
|
||||
; PlatformIO Project Configuration File
|
||||
;
|
||||
; Build options: build flags, source filter
|
||||
; Upload options: custom upload port, speed and extra flags
|
||||
; Library options: dependencies, extra library storages
|
||||
; Advanced options: extra scripting
|
||||
;
|
||||
; Please visit documentation for the other options and examples
|
||||
; https://docs.platformio.org/page/projectconf.html
|
||||
|
||||
[platformio]
|
||||
|
||||
# There should be only one env section for the DUT under test.
|
||||
# One of
|
||||
# atmega168p
|
||||
# atmega328p
|
||||
# atmega2560_timer1
|
||||
# atmega2560_timer3
|
||||
# atmega2560_timer4
|
||||
# atmega2560_timer5
|
||||
#
|
||||
[common]
|
||||
# This is the line input to StepperDemo:
|
||||
build_flags = -D SIMULATOR -D SIMAVR_TIME_MEASUREMENT
|
||||
|
||||
[env:atmega328p]
|
||||
platform = atmelavr
|
||||
board = nanoatmega328
|
||||
framework = arduino
|
||||
build_flags = -Werror -Wall ${common.build_flags}
|
||||
lib_extra_dirs = ../../../../..
|
||||
1
extras/tests/simavr_based/test_issue173/.gitignore
vendored
Normal file
1
extras/tests/simavr_based/test_issue173/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
src/
|
||||
132
extras/tests/simavr_based/test_issue173/Makefile
Normal file
132
extras/tests/simavr_based/test_issue173/Makefile
Normal file
@@ -0,0 +1,132 @@
|
||||
#
|
||||
# In order to execute the test for one directory use:
|
||||
#
|
||||
# make -C test_sd_01b_328p -f ../Makefile.test
|
||||
|
||||
SRC=$(wildcard ../../../src/*) $(wildcard src/*)
|
||||
|
||||
# platformio should contain only one env section.
|
||||
# This section states the dut name
|
||||
# atmega168
|
||||
# atmega168p
|
||||
# atmega328
|
||||
# atmega328p
|
||||
# atmega2560_timer1
|
||||
# atmega2560_timer3
|
||||
# atmega2560_timer4
|
||||
# atmega2560_timer5
|
||||
#
|
||||
|
||||
DUT=$(shell gawk '/env:/{print(substr($$1,6,length($$1)-6))}' platformio.ini)
|
||||
|
||||
TRACES=-at StepISR=trace@0x25/0x08 # PB3
|
||||
TRACES+=-at FillISR=trace@0x25/0x10 # PB4
|
||||
|
||||
#
|
||||
ifeq ($(DUT),atmega2560_timer1)
|
||||
DEVICE=atmega2560
|
||||
TRACES+=-at StepA=trace@0x025/0x20 #OC1A PB5 11 ATMega2560
|
||||
TRACES+=-at StepB=trace@0x025/0x40 #OC1B PB6 12 ATMega2560
|
||||
TRACES+=-at StepC=trace@0x025/0x80 #OC1C PB7 13 ATMega2560
|
||||
#
|
||||
else ifeq ($(DUT),atmega2560_timer3)
|
||||
DEVICE=atmega2560
|
||||
TRACES+=-at StepA=trace@0x02e/0x08 #OC3A PE3 5 ATMega2560
|
||||
TRACES+=-at StepB=trace@0x02e/0x10 #OC3B PE4 2 ATMega2560
|
||||
TRACES+=-at StepC=trace@0x02e/0x20 #OC3C PE5 3 ATMega2560
|
||||
#
|
||||
else ifeq ($(DUT),atmega2560_timer4)
|
||||
DEVICE=atmega2560
|
||||
TRACES+=-at StepA=trace@0x102/0x08 #OC4A PH3 6 ATMega2560
|
||||
TRACES+=-at StepB=trace@0x102/0x10 #OC4B PH4 7 ATMega2560
|
||||
TRACES+=-at StepC=trace@0x102/0x20 #OC4C PH5 8 ATMega2560
|
||||
#
|
||||
else ifeq ($(DUT),atmega2560_timer5)
|
||||
DEVICE=atmega2560
|
||||
TRACES+=-at StepA=trace@0x10b/0x08 #OC5A PL3 46 ATMega2560
|
||||
TRACES+=-at StepB=trace@0x10b/0x10 #OC5B PL4 45 ATMega2560
|
||||
TRACES+=-at StepC=trace@0x10b/0x20 #OC5C PL5 44 ATMega2560
|
||||
|
||||
else ifeq ($(DUT),atmega168)
|
||||
DEVICE=atmega168
|
||||
TRACES+=-at StepA=trace@0x25/0x02 #OC1A PB1 9 atmega168
|
||||
TRACES+=-at StepB=trace@0x25/0x04 #OC1B PB2 10 atmega168
|
||||
|
||||
else ifeq ($(DUT),atmega168p)
|
||||
DEVICE=atmega168p
|
||||
TRACES+=-at StepA=trace@0x25/0x02 #OC1A PB1 9 atmega168p
|
||||
TRACES+=-at StepB=trace@0x25/0x04 #OC1B PB2 10 atmega168p
|
||||
|
||||
else ifeq ($(DUT),atmega328)
|
||||
DEVICE=atmega328
|
||||
TRACES+=-at StepA=trace@0x25/0x02 #OC1A PB1 9 ATMega328
|
||||
TRACES+=-at StepB=trace@0x25/0x04 #OC1B PB2 10 ATMega328
|
||||
|
||||
else ifeq ($(DUT),atmega328p)
|
||||
DEVICE=atmega328p
|
||||
TRACES+=-at StepA=trace@0x25/0x02 #OC1A PB1 9 ATMega328p
|
||||
TRACES+=-at StepB=trace@0x25/0x04 #OC1B PB2 10 ATMega328p
|
||||
|
||||
else ifeq ($(DUT),atmega32u4)
|
||||
DEVICE=atmega32u4
|
||||
TRACES+=-at StepA=trace@0x025/0x20 #OC1A PB5 11
|
||||
TRACES+=-at StepB=trace@0x025/0x40 #OC1B PB6 12
|
||||
#TRACES+=-at StepC=trace@0x025/0x80 #OC1C PB7 13
|
||||
|
||||
endif
|
||||
|
||||
ifeq ($(DEVICE),atmega2560)
|
||||
TRACES+=-at DirA=trace@0x2b/0x01 # Pin 21 PD0
|
||||
TRACES+=-at DirB=trace@0x2b/0x02 # Pin 20 PD1
|
||||
TRACES+=-at DirC=trace@0x10b/0x80 # Pin 42 PL7
|
||||
TRACES+=-at EnableA=trace@0x2b/0x04 # Pin 19 PD2
|
||||
TRACES+=-at EnableB=trace@0x2b/0x08 # Pin 18 PD3
|
||||
TRACES+=-at EnableC=trace@0x10b/0x40 # Pin 43 PL6
|
||||
|
||||
else ifeq ($(DEVICE),$(filter $(DEVICE),atmega168 atmega168p atmega328 atmega328p))
|
||||
TRACES+=-at DirA=trace@0x2b/0x20 # Pin 5 PD5
|
||||
TRACES+=-at DirB=trace@0x2b/0x80 # Pin 7 PD7
|
||||
TRACES+=-at EnableA=trace@0x2b/0x40 # Pin 6 PD6
|
||||
TRACES+=-at EnableB=trace@0x25/0x01 # Pin 8 PB0
|
||||
|
||||
else ifeq ($(DUT),atmega32u4)
|
||||
TRACES+=-at DirA=trace@0x25/0x10 # Pin 26 PB4
|
||||
TRACES+=-at DirB=trace@0x25/0x08 # Pin 14 PB3
|
||||
#TRACES+=-at DirC=trace@0x10b/0x80 # Pin 42 PL7
|
||||
TRACES+=-at EnableA=trace@0x25/0x04 # Pin 16 PB2
|
||||
TRACES+=-at EnableB=trace@0x25/0x02 # Pin 15 PB1
|
||||
#TRACES+=-at EnableC=trace@0x10b/0x40 # Pin 43 PL6
|
||||
|
||||
endif
|
||||
|
||||
FIRMWARE=".pio/build/$(DUT)/firmware.elf"
|
||||
|
||||
DIR=$(shell env pwd)
|
||||
|
||||
ifndef SILENCE
|
||||
SILENCE=0
|
||||
endif
|
||||
|
||||
test: .tested
|
||||
|
||||
.tested: result.txt expect.txt ../judge.awk
|
||||
echo DUT=$(DUT)
|
||||
rm -f .tested
|
||||
gawk -f ../judge.awk -v DIR=$(DIR) result.txt expect.txt
|
||||
test -f .tested
|
||||
|
||||
result.txt: x.vcd
|
||||
gawk -v SILENCE=$(SILENCE) -f ../eval.awk x.vcd >/dev/null
|
||||
cat expect.txt
|
||||
|
||||
x.vcd: $(SRC) ../run_avr platformio.ini src/Issue173.ino
|
||||
~/.platformio/penv/bin/pio run -e $(DUT) || ~/.local/bin/pio run -e $(DUT) || env pio run -e $(DUT)
|
||||
../run_avr $(FIRMWARE) -m $(DEVICE) -o x.vcd $(TRACES)
|
||||
|
||||
src/Issue173.ino:
|
||||
mkdir -p src
|
||||
cd src; ln -s ../../../../../examples/Issue173/Issue173.ino .
|
||||
|
||||
clean:
|
||||
rm -fR .pio .tested x.vcd result.txt
|
||||
|
||||
20
extras/tests/simavr_based/test_issue173/expect.txt
Normal file
20
extras/tests/simavr_based/test_issue173/expect.txt
Normal file
@@ -0,0 +1,20 @@
|
||||
DirA: 0*L->H, 1*H->L
|
||||
DirB: 1*L->H, 0*H->L
|
||||
EnableA: 3*L->H, 2*H->L
|
||||
EnableB: 0*L->H, 0*H->L
|
||||
StepA: 1050*L->H, 1050*H->L, Max High=9us Total High=4119us
|
||||
StepB: 2*L->H, 2*H->L, Max High=4us Total High=9us
|
||||
Position[A]=0
|
||||
|
||||
Position[B]=2
|
||||
|
||||
Time in EnableA max=4204 us, total=8409 us
|
||||
|
||||
Time in FillISR max=1917 us, total=25558 us
|
||||
|
||||
Time in StepA max=9 us, total=4119 us
|
||||
|
||||
Time in StepB max=4 us, total=9 us
|
||||
|
||||
Time in StepISR max=5 us, total=4224 us
|
||||
|
||||
31
extras/tests/simavr_based/test_issue173/platformio.ini
Normal file
31
extras/tests/simavr_based/test_issue173/platformio.ini
Normal file
@@ -0,0 +1,31 @@
|
||||
; PlatformIO Project Configuration File
|
||||
;
|
||||
; Build options: build flags, source filter
|
||||
; Upload options: custom upload port, speed and extra flags
|
||||
; Library options: dependencies, extra library storages
|
||||
; Advanced options: extra scripting
|
||||
;
|
||||
; Please visit documentation for the other options and examples
|
||||
; https://docs.platformio.org/page/projectconf.html
|
||||
|
||||
[platformio]
|
||||
|
||||
# There should be only one env section for the DUT under test.
|
||||
# One of
|
||||
# atmega168p
|
||||
# atmega328p
|
||||
# atmega2560_timer1
|
||||
# atmega2560_timer3
|
||||
# atmega2560_timer4
|
||||
# atmega2560_timer5
|
||||
#
|
||||
[common]
|
||||
# This is the line input to StepperDemo:
|
||||
build_flags = -D SIMULATOR -D SIMAVR_TIME_MEASUREMENT
|
||||
|
||||
[env:atmega328p]
|
||||
platform = atmelavr
|
||||
board = nanoatmega328
|
||||
framework = arduino
|
||||
build_flags = -Werror -Wall ${common.build_flags}
|
||||
lib_extra_dirs = ../../../../..
|
||||
1
extras/tests/simavr_based/test_issue208/.gitignore
vendored
Normal file
1
extras/tests/simavr_based/test_issue208/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
src/
|
||||
132
extras/tests/simavr_based/test_issue208/Makefile
Normal file
132
extras/tests/simavr_based/test_issue208/Makefile
Normal file
@@ -0,0 +1,132 @@
|
||||
#
|
||||
# In order to execute the test for one directory use:
|
||||
#
|
||||
# make -C test_sd_01b_328p -f ../Makefile.test
|
||||
|
||||
SRC=$(wildcard ../../../src/*) $(wildcard src/*)
|
||||
|
||||
# platformio should contain only one env section.
|
||||
# This section states the dut name
|
||||
# atmega168
|
||||
# atmega168p
|
||||
# atmega328
|
||||
# atmega328p
|
||||
# atmega2560_timer1
|
||||
# atmega2560_timer3
|
||||
# atmega2560_timer4
|
||||
# atmega2560_timer5
|
||||
#
|
||||
|
||||
DUT=$(shell gawk '/env:/{print(substr($$1,6,length($$1)-6))}' platformio.ini)
|
||||
|
||||
TRACES=-at StepISR=trace@0x25/0x08 # PB3
|
||||
TRACES+=-at FillISR=trace@0x25/0x10 # PB4
|
||||
|
||||
#
|
||||
ifeq ($(DUT),atmega2560_timer1)
|
||||
DEVICE=atmega2560
|
||||
TRACES+=-at StepA=trace@0x025/0x20 #OC1A PB5 11 ATMega2560
|
||||
TRACES+=-at StepB=trace@0x025/0x40 #OC1B PB6 12 ATMega2560
|
||||
TRACES+=-at StepC=trace@0x025/0x80 #OC1C PB7 13 ATMega2560
|
||||
#
|
||||
else ifeq ($(DUT),atmega2560_timer3)
|
||||
DEVICE=atmega2560
|
||||
TRACES+=-at StepA=trace@0x02e/0x08 #OC3A PE3 5 ATMega2560
|
||||
TRACES+=-at StepB=trace@0x02e/0x10 #OC3B PE4 2 ATMega2560
|
||||
TRACES+=-at StepC=trace@0x02e/0x20 #OC3C PE5 3 ATMega2560
|
||||
#
|
||||
else ifeq ($(DUT),atmega2560_timer4)
|
||||
DEVICE=atmega2560
|
||||
TRACES+=-at StepA=trace@0x102/0x08 #OC4A PH3 6 ATMega2560
|
||||
TRACES+=-at StepB=trace@0x102/0x10 #OC4B PH4 7 ATMega2560
|
||||
TRACES+=-at StepC=trace@0x102/0x20 #OC4C PH5 8 ATMega2560
|
||||
#
|
||||
else ifeq ($(DUT),atmega2560_timer5)
|
||||
DEVICE=atmega2560
|
||||
TRACES+=-at StepA=trace@0x10b/0x08 #OC5A PL3 46 ATMega2560
|
||||
TRACES+=-at StepB=trace@0x10b/0x10 #OC5B PL4 45 ATMega2560
|
||||
TRACES+=-at StepC=trace@0x10b/0x20 #OC5C PL5 44 ATMega2560
|
||||
|
||||
else ifeq ($(DUT),atmega168)
|
||||
DEVICE=atmega168
|
||||
TRACES+=-at StepA=trace@0x25/0x02 #OC1A PB1 9 atmega168
|
||||
TRACES+=-at StepB=trace@0x25/0x04 #OC1B PB2 10 atmega168
|
||||
|
||||
else ifeq ($(DUT),atmega168p)
|
||||
DEVICE=atmega168p
|
||||
TRACES+=-at StepA=trace@0x25/0x02 #OC1A PB1 9 atmega168p
|
||||
TRACES+=-at StepB=trace@0x25/0x04 #OC1B PB2 10 atmega168p
|
||||
|
||||
else ifeq ($(DUT),atmega328)
|
||||
DEVICE=atmega328
|
||||
TRACES+=-at StepA=trace@0x25/0x02 #OC1A PB1 9 ATMega328
|
||||
TRACES+=-at StepB=trace@0x25/0x04 #OC1B PB2 10 ATMega328
|
||||
|
||||
else ifeq ($(DUT),atmega328p)
|
||||
DEVICE=atmega328p
|
||||
TRACES+=-at StepA=trace@0x25/0x02 #OC1A PB1 9 ATMega328p
|
||||
TRACES+=-at StepB=trace@0x25/0x04 #OC1B PB2 10 ATMega328p
|
||||
|
||||
else ifeq ($(DUT),atmega32u4)
|
||||
DEVICE=atmega32u4
|
||||
TRACES+=-at StepA=trace@0x025/0x20 #OC1A PB5 11
|
||||
TRACES+=-at StepB=trace@0x025/0x40 #OC1B PB6 12
|
||||
#TRACES+=-at StepC=trace@0x025/0x80 #OC1C PB7 13
|
||||
|
||||
endif
|
||||
|
||||
ifeq ($(DEVICE),atmega2560)
|
||||
TRACES+=-at DirA=trace@0x2b/0x01 # Pin 21 PD0
|
||||
TRACES+=-at DirB=trace@0x2b/0x02 # Pin 20 PD1
|
||||
TRACES+=-at DirC=trace@0x10b/0x80 # Pin 42 PL7
|
||||
TRACES+=-at EnableA=trace@0x2b/0x04 # Pin 19 PD2
|
||||
TRACES+=-at EnableB=trace@0x2b/0x08 # Pin 18 PD3
|
||||
TRACES+=-at EnableC=trace@0x10b/0x40 # Pin 43 PL6
|
||||
|
||||
else ifeq ($(DEVICE),$(filter $(DEVICE),atmega168 atmega168p atmega328 atmega328p))
|
||||
TRACES+=-at DirA=trace@0x2b/0x20 # Pin 5 PD5
|
||||
TRACES+=-at DirB=trace@0x2b/0x80 # Pin 7 PD7
|
||||
TRACES+=-at EnableA=trace@0x2b/0x40 # Pin 6 PD6
|
||||
TRACES+=-at EnableB=trace@0x25/0x01 # Pin 8 PB0
|
||||
|
||||
else ifeq ($(DUT),atmega32u4)
|
||||
TRACES+=-at DirA=trace@0x25/0x10 # Pin 26 PB4
|
||||
TRACES+=-at DirB=trace@0x25/0x08 # Pin 14 PB3
|
||||
#TRACES+=-at DirC=trace@0x10b/0x80 # Pin 42 PL7
|
||||
TRACES+=-at EnableA=trace@0x25/0x04 # Pin 16 PB2
|
||||
TRACES+=-at EnableB=trace@0x25/0x02 # Pin 15 PB1
|
||||
#TRACES+=-at EnableC=trace@0x10b/0x40 # Pin 43 PL6
|
||||
|
||||
endif
|
||||
|
||||
FIRMWARE=".pio/build/$(DUT)/firmware.elf"
|
||||
|
||||
DIR=$(shell env pwd)
|
||||
|
||||
ifndef SILENCE
|
||||
SILENCE=0
|
||||
endif
|
||||
|
||||
test: .tested
|
||||
|
||||
.tested: result.txt expect.txt ../judge.awk
|
||||
echo DUT=$(DUT)
|
||||
rm -f .tested
|
||||
gawk -f ../judge.awk -v DIR=$(DIR) result.txt expect.txt
|
||||
test -f .tested
|
||||
|
||||
result.txt: x.vcd
|
||||
gawk -v SILENCE=$(SILENCE) -f ../eval.awk x.vcd >/dev/null
|
||||
cat expect.txt
|
||||
|
||||
x.vcd: $(SRC) ../run_avr platformio.ini src/Issue208.ino
|
||||
~/.platformio/penv/bin/pio run -e $(DUT) || ~/.local/bin/pio run -e $(DUT) || env pio run -e $(DUT)
|
||||
../run_avr $(FIRMWARE) -m $(DEVICE) -o x.vcd $(TRACES)
|
||||
|
||||
src/Issue208.ino:
|
||||
mkdir -p src
|
||||
cd src; ln -s ../../../../../examples/Issue208/Issue208.ino .
|
||||
|
||||
clean:
|
||||
rm -fR .pio .tested x.vcd result.txt
|
||||
|
||||
18
extras/tests/simavr_based/test_issue208/expect.txt
Normal file
18
extras/tests/simavr_based/test_issue208/expect.txt
Normal file
@@ -0,0 +1,18 @@
|
||||
DirA: 0*L->H, 1*H->L
|
||||
DirB: 1*L->H, 0*H->L
|
||||
EnableA: 0*L->H, 0*H->L
|
||||
EnableB: 0*L->H, 0*H->L
|
||||
StepA: 234999*L->H, 234999*H->L, Max High=10us Total High=923957us
|
||||
StepB: 2*L->H, 2*H->L, Max High=12us Total High=25us
|
||||
Position[A]=37271
|
||||
|
||||
Position[B]=2
|
||||
|
||||
Time in FillISR max=776 us, total=1220640 us
|
||||
|
||||
Time in StepA max=10 us, total=923957 us
|
||||
|
||||
Time in StepB max=12 us, total=25 us
|
||||
|
||||
Time in StepISR max=6 us, total=894406 us
|
||||
|
||||
31
extras/tests/simavr_based/test_issue208/platformio.ini
Normal file
31
extras/tests/simavr_based/test_issue208/platformio.ini
Normal file
@@ -0,0 +1,31 @@
|
||||
; PlatformIO Project Configuration File
|
||||
;
|
||||
; Build options: build flags, source filter
|
||||
; Upload options: custom upload port, speed and extra flags
|
||||
; Library options: dependencies, extra library storages
|
||||
; Advanced options: extra scripting
|
||||
;
|
||||
; Please visit documentation for the other options and examples
|
||||
; https://docs.platformio.org/page/projectconf.html
|
||||
|
||||
[platformio]
|
||||
|
||||
# There should be only one env section for the DUT under test.
|
||||
# One of
|
||||
# atmega168p
|
||||
# atmega328p
|
||||
# atmega2560_timer1
|
||||
# atmega2560_timer3
|
||||
# atmega2560_timer4
|
||||
# atmega2560_timer5
|
||||
#
|
||||
[common]
|
||||
# This is the line input to StepperDemo:
|
||||
build_flags = -D SIMULATOR -D SIMAVR_TIME_MEASUREMENT
|
||||
|
||||
[env:atmega328p]
|
||||
platform = atmelavr
|
||||
board = nanoatmega328
|
||||
framework = arduino
|
||||
build_flags = -Werror -Wall ${common.build_flags}
|
||||
lib_extra_dirs = ../../../../..
|
||||
1
extras/tests/simavr_based/test_issue250/.gitignore
vendored
Normal file
1
extras/tests/simavr_based/test_issue250/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
src/
|
||||
131
extras/tests/simavr_based/test_issue250/Makefile
Normal file
131
extras/tests/simavr_based/test_issue250/Makefile
Normal file
@@ -0,0 +1,131 @@
|
||||
#
|
||||
# In order to execute the test for one directory use:
|
||||
#
|
||||
# make -C test_sd_01b_328p -f ../Makefile.test
|
||||
|
||||
SRC=$(wildcard ../../../src/*) $(wildcard src/*)
|
||||
|
||||
# platformio should contain only one env section.
|
||||
# This section states the dut name
|
||||
# atmega168
|
||||
# atmega168p
|
||||
# atmega328
|
||||
# atmega328p
|
||||
# atmega2560_timer1
|
||||
# atmega2560_timer3
|
||||
# atmega2560_timer4
|
||||
# atmega2560_timer5
|
||||
#
|
||||
|
||||
DUT=$(shell gawk '/env:/{print(substr($$1,6,length($$1)-6))}' platformio.ini)
|
||||
|
||||
TRACES=-at StepISR=trace@0x25/0x08 # PB3
|
||||
TRACES+=-at FillISR=trace@0x25/0x10 # PB4
|
||||
|
||||
#
|
||||
ifeq ($(DUT),atmega2560_timer1)
|
||||
DEVICE=atmega2560
|
||||
TRACES+=-at StepA=trace@0x025/0x20 #OC1A PB5 11 ATMega2560
|
||||
TRACES+=-at StepB=trace@0x025/0x40 #OC1B PB6 12 ATMega2560
|
||||
TRACES+=-at StepC=trace@0x025/0x80 #OC1C PB7 13 ATMega2560
|
||||
#
|
||||
else ifeq ($(DUT),atmega2560_timer3)
|
||||
DEVICE=atmega2560
|
||||
TRACES+=-at StepA=trace@0x02e/0x08 #OC3A PE3 5 ATMega2560
|
||||
TRACES+=-at StepB=trace@0x02e/0x10 #OC3B PE4 2 ATMega2560
|
||||
TRACES+=-at StepC=trace@0x02e/0x20 #OC3C PE5 3 ATMega2560
|
||||
#
|
||||
else ifeq ($(DUT),atmega2560_timer4)
|
||||
DEVICE=atmega2560
|
||||
TRACES+=-at StepA=trace@0x102/0x08 #OC4A PH3 6 ATMega2560
|
||||
TRACES+=-at StepB=trace@0x102/0x10 #OC4B PH4 7 ATMega2560
|
||||
TRACES+=-at StepC=trace@0x102/0x20 #OC4C PH5 8 ATMega2560
|
||||
#
|
||||
else ifeq ($(DUT),atmega2560_timer5)
|
||||
DEVICE=atmega2560
|
||||
TRACES+=-at StepA=trace@0x10b/0x08 #OC5A PL3 46 ATMega2560
|
||||
TRACES+=-at StepB=trace@0x10b/0x10 #OC5B PL4 45 ATMega2560
|
||||
TRACES+=-at StepC=trace@0x10b/0x20 #OC5C PL5 44 ATMega2560
|
||||
|
||||
else ifeq ($(DUT),atmega168)
|
||||
DEVICE=atmega168
|
||||
TRACES+=-at StepA=trace@0x25/0x02 #OC1A PB1 9 atmega168
|
||||
TRACES+=-at StepB=trace@0x25/0x04 #OC1B PB2 10 atmega168
|
||||
|
||||
else ifeq ($(DUT),atmega168p)
|
||||
DEVICE=atmega168p
|
||||
TRACES+=-at StepA=trace@0x25/0x02 #OC1A PB1 9 atmega168p
|
||||
TRACES+=-at StepB=trace@0x25/0x04 #OC1B PB2 10 atmega168p
|
||||
|
||||
else ifeq ($(DUT),atmega328)
|
||||
DEVICE=atmega328
|
||||
TRACES+=-at StepA=trace@0x25/0x02 #OC1A PB1 9 ATMega328
|
||||
TRACES+=-at StepB=trace@0x25/0x04 #OC1B PB2 10 ATMega328
|
||||
|
||||
else ifeq ($(DUT),atmega328p)
|
||||
DEVICE=atmega328p
|
||||
TRACES+=-at StepA=trace@0x25/0x02 #OC1A PB1 9 ATMega328p
|
||||
TRACES+=-at StepB=trace@0x25/0x04 #OC1B PB2 10 ATMega328p
|
||||
|
||||
else ifeq ($(DUT),atmega32u4)
|
||||
DEVICE=atmega32u4
|
||||
TRACES+=-at StepA=trace@0x025/0x20 #OC1A PB5 11
|
||||
TRACES+=-at StepB=trace@0x025/0x40 #OC1B PB6 12
|
||||
#TRACES+=-at StepC=trace@0x025/0x80 #OC1C PB7 13
|
||||
|
||||
endif
|
||||
|
||||
ifeq ($(DEVICE),atmega2560)
|
||||
TRACES+=-at DirA=trace@0x2b/0x01 # Pin 21 PD0
|
||||
TRACES+=-at DirB=trace@0x2b/0x02 # Pin 20 PD1
|
||||
TRACES+=-at DirC=trace@0x10b/0x80 # Pin 42 PL7
|
||||
TRACES+=-at EnableA=trace@0x2b/0x04 # Pin 19 PD2
|
||||
TRACES+=-at EnableB=trace@0x2b/0x08 # Pin 18 PD3
|
||||
TRACES+=-at EnableC=trace@0x10b/0x40 # Pin 43 PL6
|
||||
|
||||
else ifeq ($(DEVICE),$(filter $(DEVICE),atmega168 atmega168p atmega328 atmega328p))
|
||||
TRACES+=-at DirA=trace@0x2b/0x20 # Pin 5 PD5
|
||||
TRACES+=-at DirB=trace@0x2b/0x80 # Pin 7 PD7
|
||||
TRACES+=-at EnableA=trace@0x2b/0x40 # Pin 6 PD6
|
||||
TRACES+=-at EnableB=trace@0x25/0x01 # Pin 8 PB0
|
||||
|
||||
else ifeq ($(DUT),atmega32u4)
|
||||
TRACES+=-at DirA=trace@0x25/0x10 # Pin 26 PB4
|
||||
TRACES+=-at DirB=trace@0x25/0x08 # Pin 14 PB3
|
||||
#TRACES+=-at DirC=trace@0x10b/0x80 # Pin 42 PL7
|
||||
TRACES+=-at EnableA=trace@0x25/0x04 # Pin 16 PB2
|
||||
TRACES+=-at EnableB=trace@0x25/0x02 # Pin 15 PB1
|
||||
#TRACES+=-at EnableC=trace@0x10b/0x40 # Pin 43 PL6
|
||||
|
||||
endif
|
||||
|
||||
FIRMWARE=".pio/build/$(DUT)/firmware.elf"
|
||||
|
||||
DIR=$(shell env pwd)
|
||||
|
||||
ifndef SILENCE
|
||||
SILENCE=0
|
||||
endif
|
||||
|
||||
test: .tested
|
||||
|
||||
.tested: result.txt ../judge_pos0.awk
|
||||
echo DUT=$(DUT)
|
||||
rm -f .tested
|
||||
gawk -f ../judge_pos0.awk -v DIR=$(DIR) result.txt
|
||||
test -f .tested
|
||||
|
||||
result.txt: x.vcd
|
||||
gawk -v SILENCE=$(SILENCE) -f ../eval.awk x.vcd >/dev/null
|
||||
|
||||
x.vcd: $(SRC) ../run_avr platformio.ini src/Issue250.ino
|
||||
~/.platformio/penv/bin/pio run -e $(DUT) || ~/.local/bin/pio run -e $(DUT) || env pio run -e $(DUT)
|
||||
../run_avr $(FIRMWARE) -m $(DEVICE) -o x.vcd $(TRACES)
|
||||
|
||||
src/Issue250.ino:
|
||||
mkdir -p src
|
||||
cd src; ln -s ../../../../../examples/Issue250/Issue250.ino .
|
||||
|
||||
clean:
|
||||
rm -fR .pio .tested x.vcd result.txt
|
||||
|
||||
0
extras/tests/simavr_based/test_issue250/expect.txt
Normal file
0
extras/tests/simavr_based/test_issue250/expect.txt
Normal file
31
extras/tests/simavr_based/test_issue250/platformio.ini
Normal file
31
extras/tests/simavr_based/test_issue250/platformio.ini
Normal file
@@ -0,0 +1,31 @@
|
||||
; PlatformIO Project Configuration File
|
||||
;
|
||||
; Build options: build flags, source filter
|
||||
; Upload options: custom upload port, speed and extra flags
|
||||
; Library options: dependencies, extra library storages
|
||||
; Advanced options: extra scripting
|
||||
;
|
||||
; Please visit documentation for the other options and examples
|
||||
; https://docs.platformio.org/page/projectconf.html
|
||||
|
||||
[platformio]
|
||||
|
||||
# There should be only one env section for the DUT under test.
|
||||
# One of
|
||||
# atmega168p
|
||||
# atmega328p
|
||||
# atmega2560_timer1
|
||||
# atmega2560_timer3
|
||||
# atmega2560_timer4
|
||||
# atmega2560_timer5
|
||||
#
|
||||
[common]
|
||||
# This is the line input to StepperDemo:
|
||||
build_flags = -D SIMULATOR -D SIMAVR_TIME_MEASUREMENT
|
||||
|
||||
[env:atmega328p]
|
||||
platform = atmelavr
|
||||
board = nanoatmega328
|
||||
framework = arduino
|
||||
build_flags = -Werror -Wall ${common.build_flags}
|
||||
lib_extra_dirs = ../../../../..
|
||||
1
extras/tests/simavr_based/test_issue250_30us/.gitignore
vendored
Normal file
1
extras/tests/simavr_based/test_issue250_30us/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
src/
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user