Advertisements

Archive for category Software

Raspberry Pi Swap File Size

As part of some protracted flailing around while trying to get GNU Radio running on a Raspberry Pi 3, I discovered Raspbian defaults to a 100 MB swap file, rather than a swap partition, and everything I though I knew about swap management is now inoperative. The key hint came from some notes on gr-gsm installation.

Tweak the /etc/dphys-swapfile config file to set CONF_SWAPFACTOR=2 for a 2 GB swap file = twice the size of the Pi’s 1 GB memory.

Start it up:

sudo dphys-swapfile swapoff
sudo dphys-swapfile setup
sudo dphys-swapfile swapon

And verify it worked:

cat /proc/meminfo 
MemTotal:         949580 kB
MemFree:          194560 kB
MemAvailable:     594460 kB
Buffers:           85684 kB
Cached:           377276 kB
SwapCached:            0 kB
Active:           600332 kB
Inactive:         104668 kB
Active(anon):     250408 kB
Inactive(anon):    20688 kB
Active(file):     349924 kB
Inactive(file):    83980 kB
Unevictable:           0 kB
Mlocked:               0 kB
SwapTotal:       1918972 kB
SwapFree:        1918972 kB
Dirty:                40 kB
Writeback:             0 kB
AnonPages:        242072 kB
Mapped:           136072 kB
Shmem:             29060 kB
Slab:              33992 kB
SReclaimable:      22104 kB
SUnreclaim:        11888 kB
KernelStack:        1728 kB
PageTables:         3488 kB
NFS_Unstable:          0 kB
Bounce:                0 kB
WritebackTmp:          0 kB
CommitLimit:     2393760 kB
Committed_AS:     947048 kB
VmallocTotal:    1114112 kB
VmallocUsed:           0 kB
VmallocChunk:          0 kB
CmaTotal:           8192 kB
CmaFree:            6796 kB

Then it became possible to continue flailing …

Advertisements

, ,

Leave a comment

Prototype Board Holder: Now With Mounting Holes and Common Board Sizes

The folks I’ve been coaching through their plotter build project showed it off at the local MiniMakerFaire this past weekend. Next time around, I’ll insist they secure their circuit boards and use good wiring techniques, so as to avoid destroying more stepper drivers.

To that end, adding mounting holes to my proto board holder seems in order:

Proto Board Holder 90x70 - Flange mounting holes - Slic3r preview

Proto Board Holder 90×70 – Flange mounting holes – Slic3r preview

The board dimensions now live in an associative array, so you just pick the board name from a Configurator drop-down list:

/* [Options] */

PCBSelect = "ArdUno"; // ["20x80","40x60","30x70","50x70","70x90","80x120","ArdDuemil","ArdMega","ArdPro","ArdUno","ProtoneerCNC"]

PCB_NAME = 0;
PCB_DIMENSION = 1;

PCBSizes = [
  ["40x60",[40,60,1.6]],
  ["30x70",[30,70,1.6]],
  ["50x70",[50,70,1.6]],
  ["20x80",[20,80,1.6]],
  ["70x90",[70,90,1.6]],
  ["80x120",[80,120,1.6]],
  ["ArdDuemil",[69,84,1.6]],
  ["ArdMega",[102,53.5,1.6]],
  ["ArdPro",[53,53.5,1.6]],
  ["ArdUno",[69,53.1,1.6]],
  ["ProtoneerCNC",[69,53.1,1.6]],
];

Which seems easier than keeping track of the dimensions in comments.

You can now put the PCB clamp screws and mounting holes on specific corners & sides, allowing oddball locations for Arduino boards with corner cutouts along the right edge:

Proto Board Holder ArdUno - Slic3r preview

Proto Board Holder ArdUno – Slic3r preview

A “selector” notation separates the hole location from the board dimensions & coordinates:

ScrewSites = [
//  [-1,1],[1,1],[1,-1],[-1,-1],        // corners
//  [-1,0],[1,0],[0,1],[0,-1]           // middles
  [-1,1],[-1,-1],[1,0]                  // Arduinos
];

Might not be most obvious way, but it works for me. Most of the time, corner clamps seem just fine, so I’m not sure adding the clamp and mounting hole locations to the dimension array makes sense.

The OpenSCAD source code as a GitHub Gist:

,

Leave a comment

Mostly Printed CNC: Endstop Mount

Being a big fan of having a CNC machine know where it is, adding endstops (pronounded “home switches” in CNC parlance) to the Mostly Printed CNC axes seemed like a good idea:

MPCNC - X min endstop - actuator view

MPCNC – X min endstop – actuator view

All the mounts I could find fit bare microswitches of various sizes or seemed overly complex & bulky for what they accomplished. Rather than fiddle with screws and nut traps / inserts, a simple cable tie works just fine and makes the whole affair much smaller. Should you think cable ties aren’t secure enough, a strip of double stick tape will assuage your doubts.

A snippet of aluminum sheet moves the switch trip point out beyond the roller’s ball bearing:

MPCNC - X min endstop

MPCNC – X min endstop

I’m not convinced homing the Z axis at the bottom of its travel is the right thing to do, but it’s a start:

MPCNC - Z min endstop

MPCNC – Z min endstop

Unlike the stationary X and Y axes, the MPCNC’s Z axis rails move vertically in the middle block assembly; the switch moves downward on the rail until the actuator hits the block.

Perforce, the tooling mounted on the Z axis must stick out below the bottom of the tool carrier, which means the tool will hit the table before the switch hits the block. There should also be a probe input to support tool height setting.

The first mount fit perfectly, so I printed four more in one pass:

MPCNC MB Endstop Mounts - Slic3r preview

MPCNC MB Endstop Mounts – Slic3r preview

All three endstops plug into the RAMPS board, leaving the maximum endstop connections vacant:

MPCNC - RAMPS min endstop positions

MPCNC – RAMPS min endstop positions

Obviously, bare PCBs attached to the rails in mid-air aren’t compatible with milling metal, which I won’t be doing for quite a while. The electronic parts long to be inside enclosures with ventilation and maybe dust filtering, but …

The switches operate in normally open mode, closing when tripped. That’s backwards, of course, and defined to be completely irrelevant in the current context.

Seen from a high level, these switches set the absolute “machine coordinate system” origin, so the firmware travel limits can take effect. Marlin knows nothing about coordinate systems, but GRBL does: it can touch off to a fixture origin and generally do the right thing.

The OpenSCAD source code as a GitHub Gist:

, ,

2 Comments

Arduino Pseudo-Random White Noise Source

A reader (you know who you are!) proposed an interesting project that will involve measuring audio passbands and suggested using white noise to show the entire shape on a spectrum analyzer. He pointed me at the NOISE 1B Noise Generator based on a PIC microcontroller, which led to trying out the same idea on an Arduino.

The first pass used the low bit from the Arduino runtime’s built-in random() function:

Arduino random function bit timing

Arduino random function bit timing

Well, that’s a tad pokey for audio: 54 μs/bit = 18.5 kHz. Turns out they use an algorithm based on multiplication and division to produce nice-looking numbers, but doing that to 32 bit quantities takes quite a while on an 8 bit microcontroller teleported from the mid 1990s.

The general idea is to send a bit from the end of a linear feedback shift register to an output to produce a randomly switching binary signal. Because successive values involve only shifts and XORs, it should trundle along at a pretty good clip and, indeed, it does:

Arduino Galois shift reg bit timing

Arduino Galois shift reg bit timing

I used the Galois optimization, rather than a traditional LFSR, because I only need one random bit and don’t care about the actual sequence of values. In round numbers, it spits out bits an order of magnitude faster at 6 μs/bit = 160 kHz.

For lack of anything smarter, I picked the first set of coefficients from the list of 32 bit maximal-length values at https://users.ece.cmu.edu/~koopman/lfsr/index.html:
0x80000057.

The spectrum looks pretty good, particularly if you’re only interested in the audio range way over on the left side:

Arduino Galois bit spectrum

Arduino Galois bit spectrum

It’s down 3 dB at 76 kHz, about half the 160 kHz bit flipping pace.

If you were fussy, you’d turn off the 1 ms timer interrupt to remove a slight jitter in the output.

It’s built with an old Arduino Pro Mini wired up to a counterfeit FTDI USB converter. Maybe this is the best thing I can do with it: put it in a box with a few audio filters for various noise colors and be done with it.

It occurs to me I could fire it into the 60 kHz preamp’s snout to measure the response over a fairly broad range while I’m waiting for better RF reception across the continent.

The Arduino source code as a GitHub Gist:

,

Leave a comment

RAMPS 1.4: Configuration for Generic Motor Control

Configuring the knockoff RAMPS 1.4 board went reasonably smoothly:

RAMPS 1.4 - First Light

RAMPS 1.4 – First Light

The DC (n.b., not an AC) solid state relay in the foreground switches the 20 V laptop supply brick to the RAMPS shield atop the knockoff Arduino Mega 2560, controlled by the PS_ON pin (black wire), with +5 V from a pin in the AUX header (yellow wire). The SSR includes a ballast resistor limiting the current to 12 mA, with an inconspicuous red LED behind the black dot showing when the output is turned on.

Because it’s a DC SSR, polarity matters: the supply goes to the + terminal, the RAMPS power inputs to the – terminal.

I haven’t applied much of a load to to the SSR, but it works as expected. Define POWER_SUPPLY 1 and PS_DEFAULT_OFF so the boards starts up with the SSR turned off, then use M80 / M81 to turn it on / off as needed.

Remove D1 on the RAMPS board to isolate the Mega power from the +20 V supply. Stuffed as shown, the Mega draws 70 mA from the USB port, although an external 8 V (-ish) supply is always a good idea.

The stepper is a random NEMA 17 from the heap in a mount intended for a DIY plotter. I adjusted the tiny trimpots on all the boards for 400 mA peak = 250 mA RMS into the windings, after finding 250 mApk didn’t produce nearly enough mojo, even for a demonstration:

X Axis Stepper Drive

X Axis Stepper Drive

Just to get it running, I used DEFAULT_AXIS_STEPS_PER_UNIT = 100 step/mm, MAX_FEEDRATE 100 mm/s, and (for lack of anything better)
DEFAULT_*_ACCELERATION 1000. Those all depend the torque produced by the motor current, which is still way too low.

The endstops require X_???_ENDSTOP_INVERTING true.

I set the ?_BED_SIZE parameters to a generous 2000, with ?_MIN_POS equal to -SIZE/2 to put the origin in the middle where I prefer it, with a similar setting for the Z axis. Obviously, those numbers don’t correspond to any physical reality.

Three little 100 kΩ thermistors sprout from their header and produce reasonable temperatures, although (being cheap eBay parts) they may not match the Type 4 curve. I don’t have any heaters connected. All the over / under temperature lockouts are disabled, because I don’t care right now.

The G-Code parser wants uppercase command letters, which means I get to press the Caps Lock key for the first time in nearly forever!

The header along the right edge of the board connects to the LCD control board, which is another story.

The diffs for the Configuration.h and Configuration_adv.h files as a GitHub Gist:

,

15 Comments

Streaming Radio Player: OLED SPI Speed Fix

The OLED displays on the streaming radio players have SH1106 controllers supported by the Luma library, which works just fine. Digging into the source shows the default SH1106 setup (see the class spi() at the bottom) uses an 8 MHz clock:

    def __init__(self, spi=None, gpio=None, port=0, device=0,
                 bus_speed_hz=8000000, transfer_size=4096,
                 gpio_DC=24, gpio_RST=25):
assert(bus_speed_hz in [mhz * 1000000 for mhz in [0.5, 1, 2, 4, 8, 16, 32]])

Alas, the SH1106 doc suggests a maximum SPI clock of 2 to 4 MHz, the latter only with fair skies, a tailwind, and a stiff power supply:

SH1106 OLED Controller - SPI timing

SH1106 OLED Controller – SPI timing

The display doesn’t get updated all that often, so there’s no point in rushing things:

serial = spi(device=0,port=0,bus_speed_hz=1000000)
device = sh1106(serial)

They’ve been ticking along without mysterious blanking or mirroring for a bit over two weeks, so I’ll call it a fix.

,

Leave a comment

Google Pixel vs. USB Mounting

For reasons undoubtedly making sense at the time, the Google Pixel (and, most likely, current Android devices) don’t support the USB Mass Storage protocol. A bit of poking around suggests the jmtpfs utility supplies the other end of the Pixel’s Media Transfer Protocol and the process goes a little something like this:

  • Once upon a time, create a mountpoint: mkdir /mnt/pixel
  • Unlock the phone
  • Plug in the USB cable
  • Pull down the top menu, tap USB charging this device
  • Select Transfer Files
  • sudo jmtpfs /mnt/pixel -o allow_other,fsname="Pixel"

The allow_other parameter sets the directory / file permissions so ordinary users can access the files. The fsname is just for pretty.

The Pixel’s storage then appears as the awkwardly named /mnt/pixel/Internal\ shared\ storage/ directory.

Despite being somewhat Linuxy under the hood, the mapped storage doesn’t support the usual filesystem attributes, so don’t try to transfer them with, say, rsync -a:

rsync -rhu --progress /mnt/music/Music\ for\ Programming /mnt/pixel/Internal\ shared\ storage/Music/

When you’re done: sudo umount /mnt/pixel

This may not be a win over bankshotting off Dropbox or Google Drive, except for sensitive bits like private keys and suchlike.

Thunar apparently knows how to detect and mount mtp devices automagically and I suppose GUI-fied drag-n-drop works as you’d expect.

Leave a comment