by on Arduino

(Notes to myself #rethinkeverything)

Switch hands

  • Move the pain 
  • Rewire the brain

It’s your data…

  • Hand Copy it in Triplicate.
  • If its social then scrape it and automate it. God knows they do.

It’s your work.

  • They can’t own what you learn.
  • Redact and copy your notes in Triplicate.
  • Create/test and share open source gists/solutions
  • Make work pathways to give back to the community
  • If you have to learn it you best use it at home (lxd5/ansible/jellyfish/usw)

Work on one less thing (simplify).

  • Every convenience is a point of failure or an attack surface.
  • Git does not need to look good to be usefull. (–gitea, –gitlab, ++bare-git+hooks/mirrors)
  • — Twitter
    • with or without musk
    • also #fuckthatguy).
    • If your content is usefull it will recieve the appropriate tweets, links, usw.
    • and if it doesnt the internet is fundamentally broken.
  • If your wysywig is so unusable you don’t “blog” Throw it away. (–wordpress) 

Home is where the heart is.

  • Don’t let pi/routers do server/container work.
    • PiHole (filtering dns)
    • dhcp
    • look at virtualized routing
  • If you can’t netboot off of it is it really your network.
    • Same goes for centralized management (ldap).
    • dhcp
    • tftp
    • iscsi
  • All active work behind at least one firewall.
    • Automate pushes (including this site).
    • Streamline/cleanup html generation
    • It should also be replicated in at least one other location

Let’s go to your place.

  • Ticketing systems should be more like distributed punchnotecards. –trac
  • You shouldnt be giving out XXX bucks a month to post your public images so they can be “distributed”
    • flicker free
    • multi homed

Just because you have source control doesnt mean it’s all code

  • use markdown/git for most things.
  • but focus on the english.

Work imitates life

(What problems are we trying to solve)

  • Minimize technical debt both past and future.
  • Disentangle the various interconnected pieces and dependencies
  • Automate as much as possible
  • Document what is to be done. (Specification and sample implimentation)
  • Experience based stepwise refinement.
  1. See: Tufte’s critiq of power point.
  2. “as code” is only as good as the management understanding of the job of the people actually write and maintain it minus corporate whims, the abuse of executive privilege, and cultural constraints..

by on Arduino

In our last post we talked about wanting explore the use of two I2C based io expanders in an old school application. If it werent for the fact that there was a readymade lcd library for the mcp23017 I would have swapped the io expanders. No Pull-ups, No Pulldowns and no decent documentation on the circuitpython libraries makes the AW9523 a sucky choice for an old school keyboard matrix. But Hey, F**k It Dog. Life’s A Risk. We are gonna make do with what we have.

Looking under the keyboard membrane and tracing the connectors we can get the following key map under a 4×12 array (16 pins).

   0123456789A(10)B(11)
   --------------------
0) *# ZXCVBNM/    <STOP>
1) -LASDFGHJK<N/C><ENTER>
2) 0912345678<BS> <START>
3) POQWERTYUI<CAN><DIAL>
*#ZXCVBNM/STOP
LASDFGHJKN/CENTER
0912345678<—-START
POQWERTYUICANCELDIAL

Of course for this to work we needed to solder 10k pull up resistors on all but the last 4 pins (8-11). This was relatively straightforward since there is a strip of connectors to VIN on the board. Still, kind of a pain. On the other hand I have reals of 10k resistors and I guess I have time.

Here is a simple circtuitpython program which presents a prompt and then puts characters scanned by the keyboard onto the display.

import time
import board
import busio
import adafruit_character_lcd.character_lcd_rgb_i2c as character_lcd
import adafruit_aw9523

keymap=[]
keymap.append('*# ZXCVBNM/\001')
keymap.append('-LASDFGHJK\r\n')
keymap.append('0912345678\010\002')
keymap.append('POQWERTYUI\030\004')

lcd_columns = 24
lcd_rows = 2
i2c = busio.I2C(board.SCL, board.SDA)
lcd = character_lcd.Character_LCD_RGB_I2C(i2c, lcd_columns, lcd_rows)
lcd.message = "PiTerm 1986 v0.0\nOk >"

aw = adafruit_aw9523.AW9523(i2c)
row_pins = [aw.get_pin(8),aw.get_pin(9),aw.get_pin(10),aw.get_pin(11)]
for pin in row_pins:
   pin.switch_to_output(value=True)

col_pins = [aw.get_pin(0),aw.get_pin(15),aw.get_pin(14),aw.get_pin(13),
            aw.get_pin(12),aw.get_pin(7),aw.get_pin(6),aw.get_pin(5),
            aw.get_pin(4),aw.get_pin(3),aw.get_pin(2),aw.get_pin(1)]

for pin in col_pins:
   pin.switch_to_input(value=True)


old_row=0;
for pin in row_pins:
    pin.value=1

switch_state = [[0,0,0,0,0,0,0,0,0,0,0,0],
                [0,0,0,0,0,0,0,0,0,0,0,0],
                [0,0,0,0,0,0,0,0,0,0,0,0],
                [0,0,0,0,0,0,0,0,0,0,0,0]
               ]
while True:
    for r in range(4):
        row_pins[old_row].value=1
        row_pins[r].value=0
        old_row=r
        for c in range(12):
            if (col_pins[c].value==0 and switch_state[r][c]==0):
                switch_state[r][c]=1
                print(keymap[r][c])
                lcd.message+=keymap[r][c]
            if (col_pins[c].value==1 and switch_state[r][c]==1):
                switch_state[r][c]=0
    time.sleep(0.01)  # debounce

References

by on 8051circuitpythonRaspberry Pi

This is a snapshot of the current readme: Updates and current progress are on its github page: https://github.com/feurig/PiTerm1986

GOAL: Convert 80s style user interface ( 8031 based ADP Product: chicklet keyboard and 2×20 lcd ) to pi zero based terminal using i2c based io expanders.

Looking under the keyboard membrane and tracing the connectors we can get the following key map under a 4×12 array (16 pins).

   0123456789 10  11
   --------------------
0) *# ZXCVBNM/    <STOP>
1) -LASDFGHJK<N/C><ENTER>
2) 0912345678<BS> <START>
3) POQWERTYUI<CAN><DIAL>
*#ZXCVBNM/STOP
LASDFGHJKN/CENTER
0912345678<—-START
POQWERTYUICANCELDIAL

Keyboard

For this we look at the AW9523 GPIO expander with 16 pins of io.

LCD/VFD

Since the LCD is a 5v circuit requiring either 8 or 12 pins we look at the Microchip MCP23017 on the Adafruit GPIO Expander Bonnet which we can wire either using both ports or one port in nibble mode.

Via : https://protostack.com.au/2010/03/character-lcd-displays-part-1/

Attaching Both Boards to the Raspberry pi.

root@somepi1:/home/feurig# i2cdetect -y 1
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- -- 
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
20: 20 -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
50: -- -- -- -- -- -- -- -- 58 -- -- -- -- -- -- -- 
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
70: -- -- -- -- -- -- -- --                         

Assembly and layout.

After putting the board in the box I realized that the grey paint was conductive and that I almost let the smoke out of the pi zero. (you could smell it). So I went out and found a piece of plastic from a previous project. 

And then I was like OH SHIT I have Noritake 2×24 VFD thats a close fit..

So there’s a circuitpython library for an mcp23017 connected to an lcd. Wiring it up according to the above schematic lets us write away

root@somepi1:/home/feurig# pip3 install adafruit-circuitpython-charlcd
...
root@somepi1:/home/feurig# python3
Type "help", "copyright", "credits" or "license" for more information.
>>> import board
>>> import busio
>>> import adafruit_character_lcd.character_lcd_rgb_i2c as character_lcd
>>> lcd_columns = 24
>>> lcd_rows = 2
>>> i2c = busio.I2C(board.SCL, board.SDA)
>>> lcd = character_lcd.Character_LCD_RGB_I2C(i2c, lcd_columns, lcd_rows)
>>> lcd.message = "Hello\nPiTerm1986"
>>> lcd.clear()
>>> lcd.message = "PiTerm 1986 v0.0\nOk >"
>>> 

I am not thrilled about the way its wired but whatever.

References

by on Arduinocircuitpython

I was going to explain how we got here but. Nah. It is what it is.

This image has an empty alt attribute; its file name is IMG_3633-1024x768.jpgThis image has an empty alt attribute; its file name is IMG_3632-1024x768.jpg
#---------------------------------------------------------------epaperisslow.py
# playing around with 2.13" HD mono pi hat.
# references adafruit example code.
# screen drawing takes 9-10 seconds per update.


from datetime import datetime

def TimeString ():
    return datetime.now().strftime("%H:%M")
    
import time
import busio
import board
from digitalio import DigitalInOut, Direction

from PIL import Image
from PIL import ImageDraw
from PIL import ImageFont
from adafruit_epd.epd import Adafruit_EPD
from adafruit_epd.ssd1675b import Adafruit_SSD1675B  
import math
import random


# create two buttons
switch1 = DigitalInOut(board.D6)
switch2 = DigitalInOut(board.D5)
switch1.direction = Direction.INPUT
switch2.direction = Direction.INPUT

# create the spi device and pins we will need
spi = busio.SPI(board.SCK, MOSI=board.MOSI, MISO=board.MISO)
ecs = DigitalInOut(board.CE0) ## check back on this
dc = DigitalInOut(board.D22)
rst = DigitalInOut(board.D27)
busy = DigitalInOut(board.D17)

# give them all to our driver
display = Adafruit_SSD1675B(
    122,
    250,
    spi,  # 2.13" HD mono display (rev B)
    cs_pin=ecs,
    dc_pin=dc,
    sramcs_pin=None,
    rst_pin=rst,
    busy_pin=busy,
)
display.rotation = 1

# Create blank image for drawing.
# Make sure to create image with mode '1' for 1-bit color.
width = display.width
height = display.height
lightimage = Image.new("RGB", (width, height))
darkimage = Image.new("RGB", (width, height))

WHITE = (0xFF, 0xFF, 0xFF)
BLACK = (0x00, 0x00, 0x00)
print("clearing display")
# clear the buffer
display.fill(Adafruit_EPD.WHITE)
# clear it out
display.display()

# Get drawing object to draw on image.
light = ImageDraw.Draw(lightimage)
dark = ImageDraw.Draw(darkimage)
# empty it
light.rectangle((0, 0, width, height), fill=WHITE)
dark.rectangle((0, 0, width, height), fill=BLACK)
print("drawing box")

# Draw an outline box
light.rectangle((1, 1, width - 2, height - 2), outline=BLACK, fill=WHITE)
# Draw some shapes.
# First define some constants to allow easy resizing of shapes.
padding = 5
shape_width = 30
top = padding
bottom = height - padding
# Move left to right keeping track of the current x position for drawing shapes.
x = padding

# Load default font.

font = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf", 80)

text_origin=(7,top+15)
light.text(text_origin, TimeString(), font=font, fill=BLACK)
dark.text(text_origin, TimeString(), font=font, fill=WHITE)

print("entering the loops")

#display.image(darkimage)
#display.display()

old_ticks = time.monotonic() - 50.0
image2display=darkimage

while True:
    ticks = time.monotonic()
    # if programmer is bored: move this section to an interrupt
    if not switch1.value:
        print("Switch 1")
        image2display=lightimage
        display.image(image2display)
        display.display()
        #No point in debouncing after the display takes 9 seconds
        #while not switch1.value:
        #    time.sleep(0.01)

    if not switch2.value:
        print("Switch 2")
        image2display=darkimage
        display.image(image2display)
        display.display()
        #No point in debouncing after the display takes 9 seconds
        #while not switch2.value:
        #    time.sleep(0.01)

    # print( ticks - old_ticks)

    # Update the time on both dark and light images.
    if(( ticks  - old_ticks) >= 50.0):
        #current_time=datetime.now().strftime("%H:%M  ")
        print("updating "+TimeString())
        light.rectangle((0, 0, width, height), fill=WHITE)
        dark.rectangle((0, 0, width, height), fill=BLACK)
        light.rectangle((1, 1, width - 2, height - 2), outline=BLACK, fill=WHITE)
        light.text(text_origin,TimeString(),font=font, fill=BLACK)
        dark.text(text_origin,TimeString(), font=font, fill=WHITE)
        display.image(image2display)
        display.display()
        old_ticks=time.monotonic()
feurig@figaro:~/raspi-python-playground $ python3 epaperisslow.py 
clearing display
drawing box
entering the loops
updating 08:06
Switch 1
Switch 2
Switch 1
updating 08:07
updating 08:08
^C
feurig@figaro:~/raspi-python-playground $ cat /etc/rc.local
#!/bin/sh -e
# turn off the on board led and start the clock
echo 0 > /sys/class/leds/led0/brightness
python3 /home/feurig/raspi-python-playground/epaperisslow.py
exit 0

by on OpenWrt

The Ubiquity EdgeRouter Lite is my new favorite OpenWrt device. It is fast and inexpensive ($150 new) and the os is on a USB Stick. Stock Photo

Pros

  • 3 independent Gigabit network ports.
  • Serial Console
  • Cheap and still supported.
  • Stock Edge-os would work for most tasks.
  • OS on a USB-stick easiest backup and install EVER.
  • 512 K of memory.

Cons (some assembly required)

  • Because the stock usb stick and (unused) flash is only 4K LEDE considers it a 4K and are threatening to stop producing stock images after 19.07.
  • Third party usb sticks take longer to start up than the on board bootloader (U-boot) expects. So a pause and usb reset need to be configured.

How do I get set up?

Building 19.07 for the device

  • Getting the source. See LEDE documentation for dependencies.
feurig@vasily:~$ git clone https://git.openwrt.org/openwrt/openwrt.git
  • Building for the target
feurig@vasily:~$ cd openwrt/
feurig@vasily:~/openwrt$ make clean
feurig@vasily:~/openwrt$ git pull . v19.07.3
feurig@vasily:~/openwrt$ ./scripts/feeds update -a
feurig@vasily:~/openwrt$ ./scripts/feeds install -a
feurig@vasily:~/openwrt$ make menuconfig

    Target System (Cavium Networks Octeon)  --->
    Target Profile (Ubiquiti EdgeRouter Lite)  --->                                                                                   
    Target Images --------->
       [*] ramdisk  --->
       ***   Root filesystem archives ***
       [ ] cpio.gz
       [*] tar.gz
       ***   Root filesystem images ***
       [*] ext4  --->
       [ ] squashfs  ---- 
       [*] GZip images
           *** Image Options *** 
       (104) Root filesystem partition size (in MB) 
feurig@vasily:~/openwrt$ make -j8 download world
feurig@vasily:~/openwrt$ mv bin/targets/octeon/generic/openwrt-octeon-erlite-ext4-sysupgrade.tar.gz ~/firmware/
feurig@vasily:~/openwrt$ ./scripts/diffconfig.sh > ../firmware/openwrt-octeon-erlite-ext4-sysupgrade.diffconfig

Deploying the image

  • download the image from the build server to a local linux box.
feurig@colbert:~ $ scp feurig@wrt.suspectdevices.com:firmware/openwrt-octeon-erlite-ext4-sysupgrade.tar.gz .
  • Format the stick with 2 partitions (142M dos and the lemaining linux)
root@colbert:~ # fdisk -l
... On our machine, this is our disk ...
Disk /dev/sda: 7.6 GiB, 8166703104 bytes, 15950592 sectors
...
root@colbert:~ # fdisk /dev/sda
... Partition disk here ...
root@colbert:~ # fdisk -l
...
Disk /dev/sda: 7.6 GiB, 8166703104 bytes, 15950592 sectors
Disk model: USB 2.0 FD      
...
Device     Boot  Start     End Sectors  Size Id Type
/dev/sda1         2048  292863  290816  142M  c W95 FAT32 (LBA)
/dev/sda2       292864 3710975 3418112  1.6G 83 Linux
...
root@colbert:/home/feurig# mkfs.vfat /dev/sda1
root@colbert:/home/feurig# mkfs.ext4 /dev/sda2
  • copy firmware to usb stick
root@colbert:~ # mkdir scratch
root@colbert:~ # cd scratch/
root@colbert:~ # tar -xf ../openwrt-octeon-erlite-ext4-sysupgrade.tar.gz 
root@colbert:~ # mkdir root oroot kernel
root@colbert:~ # mount /dev/sda1 kernel/
root@colbert:~ # mount /dev/sda2 root/
root@colbert:~ # mount sysupgrade-erlite/root oroot -o loop
root@colbert:~ # cp sysupgrade-erlite/kernel kernel/vmlinux.64
root@colbert:~ # md5sum sysupgrade-erlite/kernel | cut -d' ' -f 1 > kernel/vmlinux.64.md5
root@colbert:~ # rsync -aHAX oroot/* root/
root@colbert:~ # umount kernel root oroot
root@colbert:~ # sync

Fixing the bootloader for standard USB Sticks.

  • If the usb stick used takes longer than the stock one to initialize the boot will fail.
don$ screen /dev/tty.usbserial 115200
...
U-Boot 1.1.1 (UBNT Build ID: 4670715-gbd7e2d7) (Build time: May 27 2014 - 11:16:22)
.
BIST check passed.
UBNT_E100 r1:2, r2:18, f:4/71, serial #: 802AA84CE978
MPR 13-00318-18
Core clock: 500 MHz, DDR clock: 266 MHz (532 Mhz data rate)
DRAM:  512 MB
Clearing DRAM....... done
Flash:  4 MB
Net:   octeth0, octeth1, octeth2
.
USB:   (port 0) scanning bus for devices... 
      USB device not responding, giving up (status=0)
1 USB Devices found
       scanning bus for storage devices...
No device found. Not initialized?                                                                                                                  0 
  • Getting the stock boot command
Octeon ubnt_e100# printenv               
bootdelay=0
baudrate=115200
download_baudrate=115200
nuke_env=protect off $(env_addr) +$(env_size);erase $(env_addr) +$(env_size)
autoload=n
ethact=octeth0
bootcmd=fatload usb 0 $loadaddr vmlinux.64;bootoctlinux $loadaddr coremask=0x3 root=/dev/sda2 rootdelay=15 rw rootsqimg=squashfs.img rootsqwdir=w mtd
...
  • Copy the bootcmd from the existing environment and add a delay and usb reset
Octeon ubnt_e100# setenv bootcmd 'sleep 10;usb reset;fatload usb 0 $loadaddr vmlinux.64;bootoctlinux $loadaddr coremask=0x3 root=/dev/sda2 rootdelay=15 rw rootsqimg=squashfs.img rootsqwdir=w mtd'
Octeon ubnt_e100# saveenv
Octeon ubnt_e100# reset

Adding Initial Configuration to build

In our deployment the router is maintained externally. For this reason direct login to the router as root is disabled and sudo enabled accounts are installed. These accounts connect using ssh keys and escallate privilages with their passwords. The root account is locked and ssh access is allowed from the wan port. The process for this is documented here

Once this is done the configuration can be saved to a tarball and added to the build under the files directory. These files are copied into the root filesystem of the target. The box then comes up pre configured and pre-hardened. One kludge used here is to add an rc.local which changes the users home directorys to be owned by them. Otherwise the ssh keys will not have the correct permissions.

Also /etc/sudoers, /etc/rc.local, and /home should be added to /etc/sysupgrade.conf. This way the configuration changes will be preserved while doing a sysupgrade

Rebuilding using a repo.

Now that we have a working pre-hardened build for our router we can adjust and repeat the build. (this example assumes that the build server has access to the repo)

feurig@vasily:~$ cd openwrt
feurig@vasily:~/openwrt$ git pull . v19.07.3
feurig@vasily:~/openwrt$ mv files /tmp/
feurig@vasily:~/openwrt$ git clone git@bitbucket.org:houselan/config.git files
Cloning into 'files'...
feurig@vasily:~/openwrt$ cp files/openwrt-octeon-erlite-ext4-sysupgrade.diffconfig .config
feurig@vasily:~/openwrt$ make defconfig
#
# configuration written to .config
#
feurig@vasily:~/openwrt$ ./scripts/feeds update -a
...
feurig@vasily:~/openwrt$ ./scripts/feeds install -a
...
feurig@vasily:~/openwrt$ make -j8 download world
feurig@vasily:~/openwrt$ mv bin/targets/octeon/generic/openwrt-octeon-erlite-ext4-sysupgrade.tar.gz ~/firmware/
feurig@vasily:~/openwrt$ ./scripts/diffconfig.sh > ../firmware/openwrt-octeon-erlite-ext4-sysupgrade.diffconfig 

References

Primary

by on e-bike

Last time the government gave me a significant amount of unexpected money I bought a sporterized mac 90 (a semiautomatic ak-47). This time I decided to join a different revolution. With a projected cap of $1200 I asked a friend to help me pick parts for converting a Yamaha 850 tripple to electric.

He remembered a conversion that he had helped with and now I have a complete but currently non running conversion of a 2003 Suzuki Bergman 650

by on ArduinoarmMaple BaconSite NewsSuspect Devices

Things are different.

In the 2+ years after I gave up on making things for a living a lot of things have changed. Things on my personal radar….

  • The price points for adding wifi for Q<1000 is not $15. It’s $3.
  • The Midi Manufacturers Association finally put 3.3v into the hardware standard.
  • The Non compete agreements with some of the most egregious underpaying jerks that I have ever contracted with have expired….

So….

Watch this space…..