          + Program Description
               o config.txt
               o cmdline.txt
               o trillsat.c
               o trillsat_burnsaw.sh
               o trillsat_saw_avrdude.conf
               o trillsat_burnhuck.sh
               o trillsat_huck_avrdude.conf
               o init.lua
               o trillsat.lua
               o trillsat_bot.py
               o trillsat_bot.service
               o trillsat_bbs.py
               o trillsat_pbbs_info
               o trillsat_config.py
               o trillsat_get_therm.sh
               o axports
               o ax25d.conf
               o trillsat.scad
               o trillsat_schematic.png
          + The Status Screen
          + Commands
               o ESP8266 XMPP Commands
               o Pi Bot XMPP Commands
               o Pi PBBS XMPP Commands
               o Pi PBBS Packet Radio Commands
               o THUMP Commands
               o Pi Linux Alias Commands
     * Source Code
Program Description

   (Please note that this page was originally generated in HTML. If you
   are reading this as a text README file inside the source tarball, it
   will not contain any hyperlinks and the program lines may be
   truncated.)

   Warning: This software is HIGHLY experimental! I created it for myself
   to test my TRILLSAT-1 robotic prototype; it is full of bugs and NOT
   recommended for actual use without significant changes and
   improvements. You will most likely aggravate yourself and waste a lot
   of time, energy and resources trying to replicate this project. In
   fact, even though I created the TrillSat project, I can barely
   even get the thing working myself since there are so many fragile,
   interacting components. But for me, it is a fun challenge--for you, it
   could be a nightmare.

   Also note that I am not an engineer and have created this system for my
   own use and self-education only, with the hope that providing
   information about the project will be useful to others in some way. It
   might not be suitable for you, and I am not responsible for the
   correctness of the information and do not warrant it in any way. It
   requires skills in Linux, programming, 3D printers, electronics, and
   robotics to understand many of the concepts involved. This project also
   contains references to Amateur Radio technologies that may require
   licenses in your country, but the robotic platform can be adapted to
   use license-free consumer radio technologies with varying results.

   I am hoping however, that this particular arrangement of ideas,
   systems, and modules might inspire someone, educate, or solve a problem
   somewhere.

   The home page for this project is
   http://greatfractal.com/TrillSat.html, which provides in-depth
   technical information and philosophical insights that I learned along
   the way.

   If you're reading this in the text README file and not the website,
   here's a very brief summary of this project:

   The TrillSat project was created by me, Lee Djavaherian, in St.
   Louis, Missouri in 2016 and most of the building and programming of the
   TRILLSAT-1 prototype was completed by 2018. It is an experimental,
   solar-powered, robotic radio relay with a 2m/AX.25 to WiFi/XMPP gateway
   and multi-user PBBS with in-session APRS beaconing over a single VFO.
   It has a weatherproof, temperature-controlled, low-cost design and uses
   a capstan hoist to climb a single, nylon tether to achieve high
   elevation for line-of-sight VHF, using the same drive motor for
   pendular tilt of a solar tracker. This kinematic constraint and
   catenary of the tether restricts the angle to an arcing, spiral axis
   for near dual-axis efficiency which is aligned using an accelerometer,
   Hall-effect, and LDR sensors. To counter the axial sway, the craft
   includes a passive ball damper, slow PWM startup routines, experimental
   sway-cancellation, gyroscopic reaction wheel and inertial stabilizer.
   An inductive Qi coil allows smartphone charging and a dock for a future
   LoRa "space pod". It includes mechanical energy re-capturing for motor
   assist.

   In the future, I also plan to add an experimental haptic Morse Code
   system, but this will be a separate module that won't be part of this
   software package.

   There are several source files that comprise this project:
     * The electrical schematic (drawn in KiCad)
     * The mechanical 3D-printed part generator (designed in OpenSCAD)
     * The C source code (for the 2 ATtiny's Sawyer and Huckleberry)
     * The Lua source code for the ESP8266 running NodeMCU
     * The BASH and Python source code for the Raspberry Pi Zero W

   Many of these source files also have numerous dependencies such as Arch
   Linux OS and a lot of GNU software, NodeMCU modules, C and OpenSCAD
   libraries, and Python modules, which are detailed under each of the
   sections below.

   Here are some of the main tools used at the OS level:
     * posix_ipc (for PBBS message queues)
     * socat (for testing AX.25 over pseudoterminals in simulation)
     * minicom (for initial UART testing and headless serial consoles and
       to access the ESP8266 NodeMCU console)
     * nodemcu-uploader (uploading my NodeMCU source)
     * esptool (for upgrading the ESP8266 with new versions of NodeMCU)
     * pexpect (trying to get python to use AX.25 call to interact with
       remote stations)
     * WiringPi (so BASH can set/check GPIO status)
     * pigpio (allows I2C, virtual UART, virtual PTT line, Python GPIO
       control)
     * hexdump (for decoding UV-5RA flash memory)
     * fake-hwclock (for preserving time, somewhat, across reboots)
     * kissattach (for testing AX.25 over pseudoterminals in simulation)
     * ax25d, call, beacon (ax25-tools, ax25-apps) - actual AX.25
       communication
     * Direwolf (software modem)
     * avr-gcc (C compilation of the ATtinys)
     * AVRDUDE (with bug fixes for ATtiny 1634 flash programming)
     * rsync (to allow efficient publishing of source code changes over
       ssh from another computer)
     * i2ctransfer and i2cdetect (for communicating with I2C)

config.txt

   Once Arch Linux ARM was installed on the Pi Zero W and setup via
   headless ssh remote access, changes were made to the /boot/config.txt
   file.

   Bluetooth was disabled to use the primary PL011 UART at /dev/ttyAMA0,
   1-Wire support was enabled for the DS18B20+ sensors, I2C support was
   enabled for the ESP8266 and the two ATtinys. I2C was also slowed to 50
   Khz to work around the clock-stretching bug, and PWM was enabled for
   the piezo element. The GPU memory was kept rather low to conserve
   memory since the unit is headless (but making it too low can have
   detrimental effects in some cases). It is as follows:
     __________________________________________________________________


dtoverlay=pi3-disable-bt
dtoverlay=w1-gpio

# slowed down hardware i2c to 50khz to work around rpi clock stretching bug
dtparam=i2c_arm=on
dtparam=i2c_arm_baudrate=50000

# dtoverlay=pwm,pin=18
dtoverlay=pwm-2chan,pin=18,func=2

gpu_mem=64
initramfs initramfs-linux.img followkernel

     __________________________________________________________________

cmdline.txt

   The /boot/cmdline.txt file was also configured as follows for my
   particular hardware:
     __________________________________________________________________


root=/dev/mmcblk0p2 rw rootwait console=tty1 selinux=0 plymouth.enable=0 smsc95x
x.turbo_mode=N dwc_otg.lpm_enable=0 elevator=noop

     __________________________________________________________________

trillsat.c

   The trillsat.c source file is actually a combined source file for the
   two ATtiny 1634 CPU's Sawyer and Huckleberry. This allowed me to work
   on both of them simultaneously for efficiency, as they shared much of
   the same code between them. It allowed me to visualize them both at
   once. However, there are substantial differences in their operation
   (their default pin settings are different: they are connected to
   different circuits with different functions, and they are wired to
   different reset lines.)

   So I used the C preprocessor #ifdef conditionals to only compile the
   code if SAWYER or HUCKLEBERRY is defined as 1, and this line is
   modified by the BASH scripts called trillsat_burnsaw.sh or
   trillsat_burnhuck.sh before the code is compiled and burned to the
   relevant chip. So code outside of #ifdef SAWYER or #ifdef HUCKLEBERRY
   sections is shared code, but the rest is only compiled for that
   particular chip using the intermediary files sawyer.c and
   huckleberry.c.

   The trillsat.c code is the lowest-level operating code on TrillSat and
   forms the basis of the solar, robotic platform that can carry the
   higher-level CPU's and radios. The craft can operate on only trillsat.c
   (and even partially operate with just sawyer.c or huckleberry.c
   working), but trillsat.c is designed to allow the Raspberry Pi Zero W
   and ESP8266 to send Sawyer, Huckleberry, and the LIS3DH accelerometer
   commands over their I2C lines. Due to the Pi's hardware
   clock-stretching bug, a job-queuing mechanism was created to allow
   trillsat.c to process commands and report back later, rather than tying
   up the I2C line, which also has other benefits.

   This code communicates with several sensors (CdS LDRs, Hall-effect
   sensors, voltage monitoring via ADCs, interrupt line of LIS3DH, and
   controls several switching circuits (BJTs, MOSFETs, relays, motors,
   LED).

   The trillsat.c source relies on the AVR GCC compiler and various C and
   AVR Libc libraries such as:
     * SIMTHEO.h (for the haptic Morse decoding)
     * eeprom.h
     * interrupt.h
     * sleep.h
     * io.h
     * delay.h
     * sfr_defs.h
     * math.h

   This file is expected to exist in the directory /trillsat on the root
   of the Raspberry Pi Zero W.

trillsat_burnsaw.sh

   This script is used to compile and burn the trillsat.c Sawyer code onto
   the Sawyer ATtiny 1634 microcontroller while in-circuit, using the
   Raspberry Pi Zero W's GPIO port. I typically create a BASH alias called
   burnsaw to run this script after I make changes to the trillsat.c
   source code. I keep it in the /trillsat directory.

   The script checks GPIO 5 to ensure that Huckleberry does not have the
   LED spotlight turned off and the Hall-effect sensor on that line is not
   sinking, both of which block programming on Sawyer. It instructs
   Huckleberry to turn on the LED spotlight, but exits if the Hall-effect
   sensor is sinking. This line is shared with several other functions
   since I ran out of IO pins, and the sinking issue can be remedied by
   turning the capstan a few degrees away from the sensor.

   It then compiles the script and requires that the user hit enter to
   write or "burn" the code to flash. This provides an escape point if the
   code were to error during compile, allowing me to CTRL-C to break out
   before burning. Code with errors should NOT be burned to the chip, or
   it could cause unpredictable results that could damage the device.

   This script relies on several things:
     * trillsat_saw_avrdude.conf (file below)
     * i2ctransfer (part of i2c-tools) to send the command to Huckleberry
     * i2cdetect (part of i2c-tools)
     * avr-gcc
     * avrdude
     * WiringPi

trillsat_saw_avrdude.conf

   In order to allow trillsat_burnsaw.sh to burn the correct code to
   either Sawyer or Huckleberry, it swaps out the SPI bit-bang
   programmer's reset line in AVRDUDE and then inverts it. Huckleberry's
   reset line is connected to GPIO 19 (inverted) and Sawyer's reset line
   is connected to GPIO 13 (inverted). The tilde ~ is used to invert the
   lines because I added two BJT transistors to the reset lines of Sawyer
   and Huckleberry to allow the Pi and ESP8266, which use 3.3 volt logic,
   to supply a full 5 volt high to the ATtiny 1634's reset pins. This was
   necessary since I decided to run the ATtinys at 5 volts, and the 3.3
   volt high on the reset lines was too low for reliable operation (the
   chips sporadically reset), so the transistors stabilized this, but they
   inverted the reset logic (which is why I had to use the ~ to invert
   them back). A working avrdude.conf file (found at /etc/avrdude.conf)
   should be copied to /trillsat/trillsat_saw_avrdude.conf and then edited
   to change the following lines:
     __________________________________________________________________


programmer
  id    = "linuxgpio";
  desc  = "Bitbang the Raspberry Pi Zero W GPIO to program the ATtiny 1634 calle
d Sawyer";
  type  = "linuxgpio";
  reset = ~13;
  sck   = 3;
  mosi  = 2;
  miso  = 5;

     __________________________________________________________________

   It is also worth noting that there are two bugs in the latest released
   6.3 version of AVRDUDE at the time of this writing that have to be
   fixed before it will correctly program the ATtiny 1634:

   http://savannah.nongnu.org/bugs/?40144
   http://savannah.nongnu.org/bugs/?47550

   And AVRDUDE has to be compiled with the --enable-linuxgpio=yes option
   for bitbang support. In Arch Linux, I used the Arch Build System to
   make the corrections in the source and then recompiled. Then I also
   edited this conf file and the trillsat_saw_avrdude.conf file (mentioned
   below) to add the other bug fix to the ATtiny1634 section.

   So it takes a while to get AVRDUDE working on for the ATtiny 1634
   microcontrollers first...

trillsat_burnhuck.sh

   This does mostly the same thing that trillsat_saw_avrdude.conf does
   above, except that it burns the trillsat.c source to Huckleberry
   instead (and it doesn't have to worry about the sinking Hall-effect
   sensor or itself keeping the MISO line low). But it does have to issue
   a command to Sawyer to turn off its haptic interrupt so it doesn't see
   programming signals as Morse code commands. I typically create a BASH
   alias called burnhuck to run this script.

   This script relies on several things:
     * trillsat_huck_avrdude.conf (file below)
     * i2ctransfer (part of i2c-tools) to send the command to Sawyer
     * i2cdetect (part of i2c-tools)
     * avr-gcc
     * avrdude
     * WiringPi

trillsat_huck_avrdude.conf

   Similar to trillsat_saw_avrdude.conf, this is the AVRDUDE conf file for
   Huckleberry (with its unique reset line) that also needs to be copied,
   renamed, and edited:
     __________________________________________________________________


programmer
  id    = "linuxgpio";
  desc  = "Bitbang the Raspberry Pi Zero W GPIO to program the ATtiny 1634 calle
d Huckleberry";
  type  = "linuxgpio";
  reset = ~19;
  sck   = 3;
  mosi  = 2;
  miso  = 5;

     __________________________________________________________________

init.lua

   NodeMCU on the ESP8266 runs this file at boot. I use this file to hold
   intial configuration variables (usernames, passwords, SSIDs, IP
   addresses, port) and autoconnect (in station mode) to the wifi network
   and then launch the main program trillsat.lua. Note that some server
   values are hard-coded and it expects a 24-bit network prefix (/24), the
   XMPP server name is always "esp"), and the XMPP bot username is
   "espbot".

   The init.lua (and trillsat.lua below) files require several NodeMCU
   modules to be present:
     * ADC
     * file
     * GPIO
     * net
     * node
     * ow (1-wire, but I will replace this later with DS18B20)
     * RTC mem
     * RTC time
     * timer
     * UART
     * WiFi
     * I2C (will add this later)

   Assuming NodeMCU is already installed with the correct modules,
   nodemcu-uploader is used to upload the files from the Raspberry Pi Zero
   W to the ESP8266 while in-circuit via an ssh connection.

   First, "sudo systemctl stop trillsat_bot" needs to be done to shut down
   the bot to prevent UART interaction. In Xabber, the esp needs to be
   disconnected if connected. Then the "espreset" alias is run to reset
   the ESP and bootstrap the Pi Zero W. Then the "upload" alias should be
   run which does the following:

   nodemcu-uploader --start_baud 9600 --baud 9600 --port /dev/ttyAMA0
   upload /trillsat/init.lua /trillsat/trillsat.lua

   After the upload of these two files, "espreset" should be done again,
   and then connection via Xabber should be possible to confirm it is back
   up. Then "sudo systemctl start trillsat_bot" will re-activate the bot.

trillsat.lua

   This is the main source code for the Huzzah ESP8266 board, which I have
   running NodeMCU. It contains a very basic XMPP server that I wrote to
   communicate with Xabber and is not fully standards compliant.

   It also communicates with the Raspberry Pi Zero W over the UART and can
   control the GPIO pins.

   It was designed to auto-switch to access-point mode if it loses
   connection to the Xabber smartphone, but this functionality is not
   working well with Android 6.0. Previous versions of Android would allow
   me to connect to the ESP8266 without using DNS, but Android 6.0 won't
   allow me to connect without seeing a DNS server, which breaks the
   access-point mode. I'm still trying to come up with a solution to fool
   Android into thinking that there is a real DNS server out there (as it
   is not feasible to build one on the ESP8266).

trillsat_bot.py

   This is the main program running on the Raspberry Pi Zero W, which
   allows UART communication with the ESP8266, virtual UART communication
   with the Baofeng UV-5RA radio, and I2C communication to the ATinys and
   the LIS3DH accelerometer. It performs the floating point math
   calculations needed for pitch/roll, and solar angles, and takes
   granular control over the UV-5RA flash programming to change
   frequencies on-the-fly and control the LCD display.

   It also orchestrates and facilitates communication between the remote
   packet radio callers and the station operator, routing messages between
   the multi-user PBBS instances which are spawned on connection and
   sending them over POSIX message queues and UARTs to allow XMPP
   communication.

   It updates the XMPP presence with the craft's status.

   It resides in /trillsat and requires the following Python modules.
     * serial
     * sys
     * os
     * time
     * posix_ipc
     * multiprocessing
     * threading
     * pigpio
     * mmap
     * struct
     * subprocess
     * binascii
     * pexpect
     * math
     * string

   It was written to work in both Python 2 and Python 3, but there are
   some issues at the time of this writing and Python 2 is currently used.

trillsat_bot.service

   This is the systemd service to allow trillsat_bot.py to run at boot.
   This allows the ESP8266 to turn on the Pi, and then trillsat_bot will
   begin communicating after it boots up. I copy it to
   "/usr/lib/systemd/system/" and then run "sudo systemctl enable
   trillsat_bot" to enable and "sudo systemctl start trillsat_bot" to
   start. It is as follows:
     __________________________________________________________________


[Unit]
Description=trillsat_bot

[Service]
ExecStart=/trillsat/trillsat_bot.py &> /dev/null
Restart=on-failure
RestartSec=60

[Install]
WantedBy=multi-user.target

     __________________________________________________________________

trillsat_bbs.py

   This program is spawned by ax25d whenever a remote caller connects to
   the packet station that is listening over-the-air. It may be spawned
   multiple times, once for each caller that connects, and it creates a
   unique POSIX message queue for that caller to communicate with
   trillsat_bot.py. It presents a BBS menu to each connected user, but
   also has the ability to detect calls on another port for remote text
   reception only (but there is a current bug that hasn't been solved
   yet).

   It resides in /trillsat and requires the following Python modules:
     * sys
     * os
     * time
     * posix_ipc
     * multiprocessing
     * argparse
     * termios
     * select

   It requires careful configuration of AX.25 config files.

   This was designed to work with Python 2 and Python 3, but I currently
   have it working with Python 3.

trillsat_config.py

   These are global python settings for the trillsat_bot.py and
   trillsat_bbs.py files.

trillsat_get_therm.sh

   This is a BASH script that is run once a minute via CRON using the * *
   * * * /bin/bash /trillsat/trillsat_get_therm.sh line. It generates temp
   files in the /temp folder called trillsat_thermtmp and trillsat_therm
   which are read by trillsat_bot. It has to run at least once to create
   trillsat_therm before trillsat_bot will even launch (since it looks for
   that file). It simply reads the four 1-wire DS18B20+ temp sensors via
   the Linux OS on the Pi Zero W. I had to add this script since my
   trillsat_bot code could not read those 1-wire devices without
   corruption, even if I used os-level commands. I'm not sure what is
   causing this issue, but this is a temporary work-around (with a
   1-minute delay between reads).

ax25d.conf

   This /etc/ax25/ax25d.conf file contains the callsigns and two port
   settings (the normal PBBS port and the remote text only port). This
   tells the ax25d daemon to launch trillsat_bbs.py with the correct
   delimiter, port number and callsigns when an incoming packet radio call
   is received. It is as follows:
     __________________________________________________________________


# /etc/ax25/ax25d.conf
# Using TEST01 in place of callsign for testing
[TEST01-1 via 2]
NOCALL   * * * * * *  L
default  * * * * * *  - root /trillsat/trillsat_bbs.py bbs --delimiter 13 --port
 %d --remotecallsign %U --remotecallandssid %S
#
[TEST01-2 via 3]
NOCALL   * * * * * *  L
default  * * * * * *  - root /trillsat/trillsat_bbs.py bbs --delimiter 13 --port
 %d --remotecallsign %U --remotecallandssid %S
#

     __________________________________________________________________

trillsat_pbbs_info

   This is just a text file that provides information to the remote PBBS
   caller whenever the "i - information about the PBBS" is selected from
   the menu. The Station Operator needs to edit this file before using.

axports

   The /etc/ax25/axports file associates callsigns with portnames. This
   allows calls to certain callsigns to go to certain ports, so that the
   calling station can call either the PBBS or just send a text to the
   texting port. It is as follows:
     __________________________________________________________________


# /etc/ax25/axports
#
# The format of this file is:
#
# name callsign speed paclen window description
# add TEST01 instead of callsign for testing

1 TEST01       1200     255     7     Caller
2 TEST01-1     1200     255     7     BBS
3 TEST01-2     1200     255     7     BBS Remote Text receive only

     __________________________________________________________________

trillsat.scad

   This is the OpenSCAD program that I created to generate the 3D PETG
   mechanical parts for TrillSat. Most of it is parametric, with a
   large number of variables defined in the beginning, but as it got more
   complex, I had to tweak a lot of measurements and about 25% of the code
   is riddled with hard-coded values.

   At the top of the file, you can set the showpart variable to one of
   several numbers listed to either show the individual part (which can
   then be rendered and then exported to an STL file for printing). The
   $fn variable will increase the number of fragments for smoother shapes.
   I keep it low around 20 for viewing, and set it to 200 when rendering
   to print. However, a value of 200 is very high, and takes a lot of
   computing power and several minutes to render each part. The Gyrofan
   took too many resources on my computer, so I rendered it with lower
   fragments at 100.

   Setting showpart values of 100 or larger have a special significance in
   my code, as they generate full assemblies of the entire craft:
     * 100 show full assembly
     * 101 show full assembly with tether (to calibrate angles)
     * 102 show exploded view (without Circuit Box covers)
     * 200 show animation

   It is not advisable to use large $fn values when showing the full
   assembly or animating, since it takes a very long time to render.

trillsat_schematic.png

   This is the electrical schematic for TrillSat, created in KiCAD
   and then plotted to PNG. Version 1.0 has a few typos in the comparator
   pin names for the BLDC, and the BLDC jumper has been replaced with a
   ZIF ribbon cable socket. There is also a missing 5 volts that should be
   applied on the long horizontal wire between the two photocells.

The Status Screen

   XMPP Presence is used to display the craft's status, like a mini
   dashboard display. It currently displays the following:

   Batt 1 Percentage, Batt 2 Percentage, Just Started Indicator, Roll
   Angle, Pitch Angle, Orbit Position, Solar Charge Mode, Charger Relay
   Status, Solar Charge Switch Status, Solar Power Indicator, Batt Mode
   (Series or Parallel), 5.1 on/off, 5.2 on/off, 7.1 on/off, 7.2 on/off,
   New Mail Indicator, On-the-Air Indicator, Callsigns of All Connected
   Users, Radio Frequency, Time of Day

   Many of the indicators disappear when off to allow more space for other
   items, and the smartphone can be turned sideways to expand the list if
   it gets truncated.

Commands

ESP8266 XMPP Commands

   esp hi - Tell ESP8266 to send a response to see it is working.
   esp light [on|off] - Turn the LED light on or off, Pi and Hall Sensor
   can override. Light is off at ESP boot.
   switchnet - Toggle WiFi station between AP and Client mode (button on
   Huzzah board will also do this)
   restart - Restart the ESP8266.
   [pres|pres2] - Set XMPP presence to "Hello" and "There" for testing
   purposes.
   blink - Blink Huzzah LED for testing purposes.
   pi [on|off] - Turn on or off the power to the Pi.

Pi Bot XMPP Commands

   hi - Echo greeting.
   help - Display command list. Might be obsolete. This page is more
   accurate.
   gettime - Display the time.
   settime [example 2004-02-29 16:21:42] - Set the time.
   shutdown - Gracefully shut down the Pi OS, but do not power off.
   piwifi [on|off] - Enable/disable the Pi WiFi adapter.
   pibootstrap [on|off] - Enable/disable the ability for the Pi to control
   its own power switch, but the ESP can override.
   ldo [on|off] - Enable/disable the ESP power regulator.
   light [on|off] - Enable/disable the LED light, but ESP and Hall-effect
   sensor can override.
   cds - Display the two CdS LDR/photocell voltages.
   voltage - Display Huckleberry and battery voltages.
   solar - Display the crude solar charger USB voltage.
   hall - Display the digital values of the 2 capstan Hall-effect
   switches.
   gyrohall - Display the digital values of the 3 gyro Hall-effect
   sensors.
   bldctest [testnumber] - Pulse particular U, V, or W BLDC stator coil
   patterns for 2 seconds to ensure they are working. Testnumber 1 is +U
   -V, 11 is -U +V, 2 is +U -W, 22 is -U +W, 3 is +V -W, and 33 is -V +W.
   gyro [0-255]- Start the gyro motor, gradually ramping up to set RPM in
   chunks of 40 ("gyro 7" would be 280 rpm, a good start).
   gyrorpm - Display the gyro rpm.
   gyrosetrpm [0-255] - Gradually ramp the gyro RPM on-the-fly in chunks
   of 40 ("gyrosetrpm 9" would ramp the RPM to 360, for example).
   gyrostop - Stop the gyro motor.
   [--|-+|++|+-] Drive the capstan H-Bridge without PWM.
   park - Perform the 3 tridant orbital mechanics to move the planetary
   mass to sunrise position, lifting the craft.
   orbit [1|0] [0-255] - Move drive motor to noon, then perform a full
   orbit back to noon. First parameter is direction, second is number of
   orbits.
   ramp [1|0] [acceleration] [1|0] [speed] [sustain] [position] - Slowly
   ramp up, then down capstan motor, the first value is drive type
   (1=locked antiphase, 0=sign-magnitude), second value is acceleration
   (0|1-127|127-254). A value of 0 is instant acceleration, a value of
   1-127 is slow-to-fast acceleration (with lower values fastest), a value
   of 128-254 is fast-to-slow deceleration (with higher values fastest).
   The 3rd value is direction (1=up, 0=down), the 4th value is max speed
   to ramp up to (0-255), the last value is sustain of max speed in chunks
   of 10ths of a second, so 10=1 second sustain. There is a dead stop when
   the sensor reaches noon, so this command is mainly for testing.
   rotate [direction] position - Ramp up to a hall-sensor "clock
   position". Direction is [1|0] for up/down the rope. Positions are
   compass degrees: 0 is noon, 90 is sunrise, 270 is sunset, 180 is
   midnight, 1 is morning, 359 is afternoon and the travel path and exact
   stop points can vary depending on direction. Speed and acceleration and
   max travel time are fixed, but if it hits the position it comes to an
   abrupt stop to stay on position.
   dtemp - Read the 4 DS18B20+ temp sensors, display in Fahrenheit. Only
   updated once per minute due to cron script to workaround a bug.
   pitemp - Read the Raspberry Pi Zero W GPU/CPU temp in Fahrenheit.
   tinytemp - Read the two ATtiny CPU temp sensors in Fahrenheit.
   (calibrated to DS18B20+ at boot).
   listemp - Read the LIS3DH accelerometer temp sensor in Fahrenheit.
   (calibrated to DS18B20+ at boot).
   pc - Clear PWM and turn capstan motor off.
   [s|p] - Serial or parallel battery mode.
   charge [1|2] - Set solar charger relay to batt 1 or 2.
   chargeswitch [on|off] - Enable/disable solar charger power.
   [5.1|5.2|7.2|7.2] [on|off] - Enable/disable 5 or 7.4 volt boost
   converter for that battery.
   qi [on|off] - Enable/disable Qi wireless charger.
   chargemode [on|off] - Enable/disable automatic solar charge mode.
   radio [on|off] - Enable/disable the UV-5RA radio power.
   [huckctc|sawctc] [0-255] - Set the CTC OCR0A timer value on-the-fly for
   Huckleberry or Sawyer.
   pulse - Instruct Sawyer to send a short haptic motor pulse for testing.
   pulsemode [1|0] - Set the morse_echo and morse_replay variables
   differently on the two ATtinys to enable haptic mode (1) or LED mode
   (0)
   thump [1|0] - Turn the THUMP interrupt on or off
   cfg [0-255] - Set CLICK_CFG register to set click direction (1 is x, 4
   is y, 16 is z, add for combos)
   ths [0-255] - Set CLICK_THS register to change threshold (for changing
   the sensitivity)
   limit [0-255] - Set TIME_LIMIT register
   latency [0-255] - Set TIME_LATENCY register (for changing the pulse
   width)
   window [0-255] - Set TIME_WINDOW register
   ref - Read DC acceleration and set LIS3DH REFERENCE register to
   subtract it.
   hucklight [1|0] - Tell Huckleberry to turn on LED Spotlight (which
   frees up MISO line).
   code [A-Z][A-Z] - Set a two-capital-letter haptic passcode in EEPROM on
   two the ATtinys. If two capital letters are not added (such as numbers
   or lower-case letters) it unlocks the haptic command system.

Pi PBBS XMPP Commands

   beacon - Send beacon.
   ota - Toggle on-the-air mode.
   c - Toggle chat mode.
   r - Read all messages.
   d - Delete all messages.
   away - Set away mode.
   m [recipient] [message text] - Create store-and-forward e-mail.
   text [recipient] [message text] - Send real-time text message.
   c [recipient] - Accept chat request and enable chat mode.
   endchat - Exit chat mode.

Pi PBBS Packet Radio Commands

   i - information about this PBBS
   m - send message to station operator (/EX when done)
   c - request live chat with station operator
   ? - help - show command menu
   b - bye (disconnect)

THUMP Haptic Commands

   X (-..- . .... - Disable all power to the craft, including power to the
   ATtiny itself (if it is night, the craft will then be completely dead)
   P (.--. .. . .) - Power up 5.2 boost_converter and ESP8266
   L (.-.. .. ..) - Turn on the ESP8266 (via its LDO regulator)
   B (-... . ...) - Turn on the 5v boost converter on Batt 2
   Q (--.- . . ...) - Turn on the Qi charger (important if the smartphone
   is dead and needs to charge to regain XMPP control)

Pi Linux Alias Commands

   These commands can be used on the Linux BASH shell running on the
   Raspberry Pi Zero W. They are mainly for my own convenience during
   programming. I need to add more of them in the future, as they are
   important in situations when the ESP8266 is unavailable and all I have
   is SSH access over the Pi Zero WiFi.

   esp - connect to ESP8266 NodeMCU via Minicom at 115200 baud
   espslow - connect to ESP8266 NodeMCU via Minicom at 9600 baud
   upload - use nodemcu-uploader at 9600 baud to upload Lua source files
   to ESP8266 NodeMCU
   bot - launch the bot process that controls the core functions of the
   craft
   scat - use socat to create two linked pseudoterminals
   bbs - launch PBBS on port 2 for internal testing using linefeed
   delimiters
   bbsr - launch PBBS on port 2 for internal testing using carriage return
   delimiters
   bbst - launch PBBS on port 3 for internal testing of XMPP text
   reception using linefeed delimiters
   burnhuck - compile and write C source code to ATtiny 1634 flash
   (Huckleberry)
   burnsaw - compile and write C source code to ATtiny 1634 flash (Sawyer)
   huckreset - hard reset the ATtiny 1634 (Huckleberry)
   sawreset - hard reset the ATtiny 1634 (Sawyer)
   espreset - bootstrap the Pi Zero W (so it doesn't lose power) and hard
   reset the ESP8266

   Here is the actual code that can be added to the .bashrc file:
     __________________________________________________________________


alias esp='minicom -b 115200 -o -D /dev/ttyAMA0'
alias espslow='minicom -b 9600 -o -D /dev/ttyAMA0'
alias upload='nodemcu-uploader --start_baud 9600 --baud 9600 --port /dev/ttyAMA0
 upload /trillsat/init.lua /trillsat/trillsat.lua'
alias bot='sudo /trillsat/trillsat_bot.py'
alias scat='socat -d -d pty,raw,echo=0 pty,raw,echo=0'
alias bbs='sudo /trillsat/trillsat_bbs.py -n 10 -d 2 -U TEST01 -S TEST01-1'
alias bbsr='sudo /trillsat/trillsat_bbs.py -n 13 -d 2 -U TEST01 -S TEST01-1'
alias bbst='sudo /trillsat/trillsat_bbs.py -n 10 -d 3 -U TEST01 -S TEST01-2'
alias burnhuck='bash /trillsat/burnhuck.sh'
alias burnsaw='bash /trillsat/burnsaw.sh'
alias huckreset='gpio -g mode 19 out;gpio -g write 19 1;gpio -g mode 19 in;sudo
i2cdetect -y 1'
alias sawreset='gpio -g mode 13 out;gpio -g write 13 1;gpio -g mode 13 in;sudo i
2cdetect -y 1'
alias espreset='echo "Bootstrapping Pi and resetting ESP...";gpio -g mode 20 out
;gpio -g write 20 1;gpio -g mode 6 out;gpio -g write 6 0;gpio -g mode 6 in'

     __________________________________________________________________

Disclaimer

   Warning, this project is experimental and not recommended for real data
   or production. Do not use this software (and/or schematic, if
   applicable) unless you read and understand the code/schematic and know
   what it is doing! I made it solely for myself and am only releasing the
   source code in the hope that it gives people insight into the program
   structure and is useful in some way. It might not be suitable for you,
   and I am not responsible for the correctness of the information and do
   not warrant it in any way. Hopefully you will create a much better
   system and not use this one.

   I run this software because it makes my life simpler and gives me
   philosophical insights into the world. I can tinker with the system
   when I need to. It probably won't make your life simpler, because it's
   not a robust, self-contained package. It's an interrelating system, so
   there are a lot of pieces that have to be running in just the right way
   or it will crash or error out.

   There are all kinds of bugs in it, but I work around them until I later
   find time to fix them. Sometimes I never fix them but move on to new
   projects. When I build things for myself, I create structures that are
   beautiful to me, but I rarely perfect the details. I tend to build
   proof-of-concept prototypes, and when I prove that they work and are
   useful to me, I put them into operation to make my life simpler and
   show me new things about the world.

   I purposely choose to not add complexity to the software but keep the
   complexity openly exposed in the system. I don't like closed,
   monolithic systems, I like smaller sets of things that inter-operate.
   Even a Rube Goldberg machine is easy to understand since the
   complexities are within plain view.

   Minimalism in computing is hard to explain; you walk a fine line
   between not adding enough and adding too much, but there is a "zone", a
   small window where the human mind has enough grasp of the unique
   situation it is in to make a difference to human understanding. When I
   find these zones, I feel I must act on them, which is one of my
   motivating factors for taking on any personal project.

   Here is an analogy: you can sit on a mountaintop and see how the tiny
   people below build their cities, but never meet them. You can meet the
   people close-up in their cities, but not see the significance of what
   they are building. But there is a middle ground where you can sort of
   see what they are doing and are close enough to them to see the
   importance of their journey.

   The individual mind is a lens, but, like a single telescope looking at
   the night sky, we can either see stars that are close or stars that are
   much farther away, but we can't see all stars at the same time. We have
   to pick our stars.

   I like to think of it like this:

   It is not within our power to do everything, but it is within our
   power to do anything.
     __________________________________________________________________


