Skip to content

NomiChirps/tplp2

Repository files navigation

TPLP2

Building

Install bazel (or bazelisk), gcc-arm-none-eabi, arm-none-eabi-newlib. Developed with gcc-arm-12.1.0.

# debug build
bazel build //tplp:firmware.uf2
# optimized build
bazel build //tplp:firmware.uf2 -c opt

# firmware blob is in bazel-bin
ls -lh bazel-bin/tplp/firmware.uf2

TODO / Notes

  • P1: motor speed pulsates while microstepping. fix this! it's important!

  • don't like the pid algorithm from wikipedia. the proportional term is weird. let's find another one

  • statically allocate all the instances of my hardware classes. we aren't going to be adding a third stepper motor at runtime, you dork.

    • done for StepperMotor
  • Milestone: Paper Tensioning

    • Be able to load paper and feed it forward and backward while maintaining correct tension.
    • needs steppers working
    • needs load cell persistently calibrated & installed
      • save settings button
      • manual calibration gui
      • auto calibrate/zero button (& algorithm)
    • needs a PID loop with all the accoutrements
      • one loop watches printer roller encoder and controls CENTER of motor target positions
      • one loop watches load cell and controls DIFFERENCE between motor target positions
      • and two MORE loops watch motor target positions and controls motor speeds & directions. maybe those aren't pid though - something about a minimum jerk trajectory? idk.
      • this also means we need to actually install the encoder sooner rather than later.
      • i still want a mathematically sound PID tuning UI. or i guess procedure, if i expose everything in the new params ui.
    • hah, interesting thought... should we use some kind of online state estimation (Kalman filter???) to keep track of the relative radius of the rolls? observe that when moving the rollers at equal but opposite angular velocities, the roll with the greater radius causes the print roller to turn slightly in its direction while tension increases. when the radii are equal, tension would increase while the print roller stays motionless. ... if we can estimate this, would it even be useful? hmmmmmmmmmmmmmmmmmmmmmm
  • I2cController doesn't fail gracefully when a read times out!

  • Create a front panel UI (assignee: wembly :)

    • runtime stats / logging screen
    • (later) print status / job control / main screen ?
    • remove the "home" screen, just use that left sidebar for everything. but also hide/delete it when not in use: to free up horizontal space on the screen and to conserve RAM.
    • some kind of display for non-fatal errors. modal dialog box? little icon in the corner to tap on and expand? idk.
      • went with a simple modal
    • manual motor control screen
    • I2C bus scan
    • virtual class interface for callbacks 'n' stuff
    • Use LVGL
  • Get peripheral hardware running

    • Roller encoder
      • neglected to add this to the original hardware design ;(
    • Laser module (PWM control)
    • Mirror motor (PWM control; still needs a driver circuit)
    • Mirror optointerrupter
    • pinhole photodiode for self-calibration and/or self-test
    • MicroSD card reader
      • we may want two. the one in the display is very difficult to access, so it's more suited to being the internal storage.
      • alternatively, forget using SD cards to upload and go ahead with the wi-fi interface, haha
        • an embedded target and a command-line client tool, in the same project? time for bazel to shine ~
    • Stepper drivers
    • HX711 load cell reader
    • Shiny new front panel display + LVGL driver
    • touchscreen input (SPI breakout)
    • Sharp LCD display + LVGL driver
  • Transfer electronics to a PCB with 12v supply when finalized.

  • loadcell needs its own (shielded?) cable with really good clean connectors that don't jiggle

  • 32-bit aligned reads and writes are atomic. It would be nice to take advantage of that and avoid some locking where possible.

    • update: yes indeed, i certainly have been getting sloppy about locking. will i regret it? time will tell.

Nice to have

  • bring parameter values back and save them in source control at some point. maybe do this automatically somehow (parse the startup log? simple, dirty, works)
  • stepper driver: should coils be set to freewheel (LL) or short-brake (HH) at the top of each command cycle? maybe experiment with it.
  • factory reset button (restoring all params to default, e.g. by deleting the config dir)
  • fatal error handler to display the stack trace on the GUI before crashing
    • will require support from picolog. make sure picolog prevents the crashed task from proceeding, and has a watchdog or something to finish crashing the device if the fatal error handler doesn't finish in time.
  • audit codebase for portMAX_DELAY, CHECK, etc. and make sure everything that can fail "gracefully", does.
  • JTAG? is that a thing i can do?
  • rename all the lvgl_driver.cc to have distinct module names for VLOG
  • clear the display on boot. the random pixels look kinda cool but...
    • actually, no 'clear' command exists. best we can do is turn off the pixels (command 22h, pp.139), do a full memory write, and turn them back on.
  • TSC2007 lvgl driver should debounce, buffer, and interpolate
  • I2cController needs nonblocking operations, coalescing commands, general TLC
  • hook up tft backlight pin and add an adjustable brightness setting (PWM)
  • fix "bazel test //..." by adding target_compatible_with where appropriate
    • this may also involve fixing up rules_pico to make correct use of the defines PICO_NO_HARDWARE and PICO_ON_DEVICE
  • generate & examine .map file for the firmware blob
  • use bloaty to find things to trim off the firmware size
    • random forum post recommends copts "-ffunction-sections -fdata-sections" and ldopts "–gc-sections"
  • Vendor all 3rd party libraries
  • split out various things i'm proud of as their own librar(ies)
  • write stress tests for SpiController/I2cController. lotsa tasks, lotsa devices, all hammering away

Board configuration/pins

Pinout / Peripherals

See tplp/tplp_config.h for pin and GPIO assignments.

Bus Devices
SPI0 -
SPI1 HX8357; SD Card
I2C0 TSC2007
I2C1 -

Stepper driver ribbon cable layout

  • Pin 1 (red) - ENA
  • Pin 2 - IN1
  • Pin 3 - IN2
  • Pin 4 - IN3
  • Pin 5 - IN4
  • Pin 6 - ENB

Load cell connector

  • Pin 1 - Red - E+
  • Pin 2 - Black - E-
  • Pin 3 - Green - A-
  • Pin 4 - White - A+

Debugging

Note that USB serial stdio is not available while debugging because pico-debug uses the USB port.

Setup

  1. You will need to have the standard GNU autotools/configure/make toolchain installed on your system, for building OpenOCD.
  2. Make sure you'll have the appropriate permissions to access the pico-debug CMSIS-DAP USB device; this can be accomplished by adding a udev rule and adding yourself to the plugdev group mentioned in that rule (or edit the rule to use a different group).
  3. If using Visual Studio Code, install the "Cortex-Debug" extension.
  4. If not using Visual Studio Code, build OpenOCD: cd third_party/openocd; bazel build //:openocd. This will download and compile the appropriate version of OpenOCD within the Bazel sandbox, leaving the binaries in third_party/openocd/bazel-bin/external/openocd/openocd/bin/openocd and the scripts dir in third_party/openocd/bazel-bin/external/openocd/openocd/share/openocd/scripts. Isn't it funny how if you say openocd enough times it doesn't sound like a real word anymore?

To debug under VSCode

See also: https://github.com/majbthrd/pico-debug/blob/master/howto/vscode1.md

  1. Put Pico into bootloader mode (reset while holding BOOTSEL).
  2. Run the flash pico-debug task in VSCode. This downloads a prebuilt pico-debug image and copies it to the device. Pico is now running the debugger on core 1.
  3. Build tplp in debug mode by running the [debug] build task.
  4. Launch the debug configuration in VSCode ("Run and Debug" tab). This is defined in .vscode/launch.json. This will also download and build OpenOCD first, if it hasn't already.
  5. The program should automatically be loaded onto the Pico and start running in the debugger.
  6. You can restart the program freely, but ending the debug session means you'll need to reflash pico-debug to start again. In order to make changes and restart, run the [debug] build task and then issue the load command in the debug console. Wait for the transfer to finish before hitting the Restart button (Ctrl+Shift+F5).

To debug without IDE support

See also https://github.com/majbthrd/pico-debug/blob/master/howto/openocd.md.

  1. Put Pico into bootloader mode (reset while holding BOOTSEL).
  2. Run bazel run //tools:flash-pico-debug, which downloads a prebuilt pico-debug binary and copies it to the device. Pico is now running the debugger on core 1.
  3. Start the OpenOCD server: third_party/openocd/bazel-bin/external/openocd/openocd/bin/openocd -s third_party/openocd/bazel-bin/external/openocd/openocd/bin/openocd -f interface/cmsis-dap.cfg -f target/rp2040-core0.cfg -c "transport select swd" -c "adapter speed 4000". It should connect to the Pico and wait for commands.
  4. Build tplp in debug mode: bazel build --config=picodebug //tplp:firmware.elf
  5. Start GDB: arm-none-eabi-gdb bazel-bin/tplp/firmware.elf.
  6. Connect GDB to OpenOCD: (gdb) target remote localhost:3333.
  7. Load the target into flash: (gdb) load.
  8. Start it: (gdb) monitor reset init, (gdb) continue.

Reference Materials

todos whomst done

  • P0: finish making my type-safe fixpoint thing so i can implement the PROPERLY discretized pid algorithm from wikipedia
  • redesign manual stepper control UI to match the new API and to be easier to use
  • P1: fix major stepper glitch when reversing direction
  • P1: Okay we REALLY need to be able to dial the motor speed ALL the way down right next to zero. the pid loop is not happy otherwise.
  • FIXME: go through all my uses of __not_in_flash and add asserts to make sure they're actually doing that thing (addr < 0x1000000)
  • stepper timer interrupt isn't doing the right thing w.r.t. rearming the alarm. fix that. maybe make a template from the impl in paper_controller.
  • (!!!) steppers need to be able to go slower! a lot slower!
    • When hz is below the threshold, switch from DMA timer + DREQ to a timer interrupt (high priority, probably?)
  • Clean up the prototype electronics
    • remember to power pico thru VSYS, not VBUS, to avoid potentially sending power upstream to the usb host
    • supply 5V to HX711
    • Add bus capacitors
  • fix all instances of std::setw(). it only sticks for one output field...
  • Begin() Setup() Init(), PICK ONE
  • UX Improvements
    • fix everything in the ui being scrollable
    • numeric display of load cell value & raw value
    • oops changed my mind about the load cell units. they're actually completely arbitrary.
  • need a thingy for persistently saving global parameters / preferences / whatever you wanna call em.
  • alright fine let's get StrCat in here sheeeeesh
  • SpiController could use improvement - we're not getting full utilization of the bus
    • verdict: use the new DmaController with nonblocking operations where possible, and that's gonna be good enough.
  • Load cell time!
    • hx711 pio driver
    • gui for monitoring & calibration
    • print some brackets to calibrate it against my digital scale
  • put the load cell period (100ms) in constants.h
  • read about the hardware interpolators in rp2040
    • does what it says on the tin. good for linear scaling, affine texture mapping, that kinda thing.
  • Mission: DMA 9000
    • see new ideas in tplp/bus/dma.h !!!
    • SpiController needs to take advantage of the new Action stuff to be more nonblocking, and actually make use of the DmaManager queue.
      • to manage CS easily we might need before-Actions as well as after-Actions!
    • I2cController needs... uh... idk i don't want to look at it right now
    • after action report: the new ideas in tplp/bus/dma.h were waaaay too complicated and not actually a performance improvement. went back to the now-current implementation and fixed up SpiController/I2cController to take advantage of its async features.
      • I NEVER WANT TO LOOK AT DMA AGAIN >:(
  • Install jumpers on the stepper drivers (to configure internal 5v power supply)
  • figure out who's allowed to call xTaskCreate. centralize it.
  • forget the std::duration stuff.. really not worth the hassle.
  • rename SpiManager -> SpiController
  • insert appropriate delays in TSC2007 read cycle; we have noise problems
  • consider removing all deletions of FreeRTOS objects and switching to heap_1
    • I considered it. it's not gonna happen
  • move/redirect config headers to a config/ dir
  • (?!) display fails self-test during startup if usb-serial output not present
    • the issue was it needed some time to boot up after poweron before accepting commands
  • LVGL driver for HX8357
  • HX8357 self test :)
  • rework SpiController again again; it should be able to suport full duplex. instead of sendevent/receiveevent, let's have transferevent(naming???) which specifies optionally both buffers. I GUESS???? if both are specified, they would necessarily have to be the same length!
  • get a compile_commands going for //simulator
  • have FreeRTOS and LVGL running together in a simulator mode on the host, for UI development (and unit testing?!)
  • fix lvgl+simulator so it doesn't build SDL2 twice
  • it is time to reorganize the directory structure again
    • we've got /openocd, /lib, /picolog, /tplp... too many different kinds of things at the top level
  • bazel build for OpenOCD binary!
  • WONTFIX: run blaze with layering_check; but need to do it on Linux because it requires CC=clang. might also need to add clang support to rules_pico.
    • this definitely isn't gonna happen. it needs support from the toolchain definition and i don't want to research how to implement that.
  • fix compile_commands extraction, again (problem with lvgl build? maybe strip_include_prefix works correctly on Linux?)
  • Why are we spending so much time in Tmr Svc?
    • it's actually not that much time now, without SMP.
  • please let's replace tplp_assert() with CHECK(), CHECK_NOTNULL(), etc. likewise DebugLog() -> LOG(INFO), VLOG(1), etc.
    • Implemented "picolog" and broke it out into a library :)
  • switch to Linux because wow gosh heckie does windows suck for this kind of development
  • create a lint.sh or something. to cover cc and bzl files (using Trunk vscode extension)
  • spend a week fruitlessly debugging instability between FreeRTOS-SMP + pico-sdk before giving up on SMP in disgust. at least I learned a lot and ironed out a few other issues along the way.
  • vApplicationGetIdleTaskMemory mystery: why doesn't my definition clash with the rp2040 port's in idle_task_static_memory.c?
    • ah. because i needed alwayslink=1 in FreeRTOS. it's fine though, we don't need to add it. the local definition gets linked in just fine.
  • (vanity) rename FreeRTOS or FreeRTOS-Kernel to the same thing, so we can say e.g. "@FreeRTOS" instead of "@FreeRTOS-Kernel//:FreeRTOS"
  • Tune FreeRTOS
    • The verdict: we'll be using non-SMP with preemption. If we need the second core for something, we'll put it there manually.
    • enable SMP/multicore
      • turns out this was a terrible idea.
    • audit FreeRTOSConfig.h
    • (friendship ended with Arduino) audit Arduino compat libraries for blocking delays?
    • (friendship ended with Arduino) use scope to verify reliability in the presence of Arduino libs
    • write configASSERT handler (use the NeoPixel LED?)
  • use the genrule() trick to finally encapsulate FreeRTOS headers
  • use DMA for the Sharp LCD driver, just for funsies
  • figure out how to track TODO/FIXME/XXX in IDE
  • organize source code under src/ (I changed my mind later)
  • (it's not possible, i decided) refer to FreeRTOS headers with a prefix, if possible (actually it is)
  • Make sure we're not using floating point math anywhere (including dependencies): discovered via std::unordered_map that we panic if any floating point math is used
  • Reset to the bootloader without touching the board: magic 1200 baud connection
  • Get FreeRTOS running
  • Bazel-ify the build

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published