The Smell of Molten Projects in the Morning

Ed Nisley's Blog: Shop notes, electronics, firmware, machinery, 3D printing, laser cuttery, and curiosities. Contents: 100% human thinking, 0% AI slop.

Category: Photography & Images

Taking & making images.

  • SJCAM M20 Camera: Car Mode Battery Hack

    SJCAM M20 Camera: Car Mode Battery Hack

    The last lithium cell (a.k.a. battery) for the longsuffering SJCAM M20 transformed itself into a spicy pillow:

    SJCAM M20 - spicy pillow lithium battery
    SJCAM M20 – spicy pillow lithium battery

    SJCAM no longer sells those batteries and nobody else does, either, surely because the +4.35V marking shows they’re a special-formula high-voltage lithium mix that doesn’t work with ordinary chargers. Worse, you can’t substitute an ordinary (i.e. cheap) battery, because applying a high-voltage charger to a 4.2 V cell makes Bad Things™ happen.

    Putting the M20 camera in Car Mode makes it begin recording when it sees 5 V on its USB input and shut down a few seconds after the USB input drops to 0 V. Without the internal battery, the camera’s clock doesn’t survive when the external power vanishes, which seems critical for a camera sitting on a dashboard.

    Mashing all that together, I wondered if I could use one of the many leftover low-voltage NP-BX1 batteries from the Sony AS30V helmet camera without starting a dashboard fire, by preventing the camera from charging the battery, while still using it when the USB input is inactive (which, for our car, is pretty nearly all the time).

    The circuitry, such as it is, uses a cheap 1S USB charge controller and a Schottky diode:

    SJCAM M20 Car-Mode Battery Hack - circuit doodle
    SJCAM M20 Car-Mode Battery Hack – circuit doodle

    Power comes in on the left from a USB converter plugged into the Accessory Power Outlet in the center console and goes out to the camera’s USB jack, using a butchered cable soldered to the charge controller’s pads in the middle. The controller manages the NP-BX1 battery as usual, but a diode prevents the camera from trying to send charge current into the controller.

    This should just barely work, as the diode reduces the battery voltage by a few hundred millivolts, so the camera will see the fully charged low-voltage battery as a mostly discharged high-voltage battery.

    Suiting action to words:

    SJCAM M20 Battery Replacement - circuitry
    SJCAM M20 Battery Replacement – circuitry

    It’s built inside the gutted remains of an M20 battery case. The 100µF tantalum cap provides local buffering to prevent the camera from browning out during bursts of file activity while recording. The wire emerges through holes gnawed in the battery case and the camera housing:

    SJCAM M20 Battery Replacement - camera cable exit
    SJCAM M20 Battery Replacement – camera cable exit

    The charge controller on the other end of the wire lives in a layered laser-cut acrylic case attached to a modified version of the venerable 3D printed NP-BX1 battery holder:

    SJCAM M20 Battery Replacement - charger wiring
    SJCAM M20 Battery Replacement – charger wiring

    More on the cases tomorrow.

    Putting it all together, the lashup goes a little something like this:

    SJCAM M20 Battery Replacement - trial install
    SJCAM M20 Battery Replacement – trial install

    The battery pack will eventually get stuck to the dashboard underneath the overhang, out of direct sunlight. Things get hot in there, but with a bit of luck the battery will survive.

    The rakish tilt puts the hood along the bottom of the image, although raising the camera would reduce tilt and cut down on the skyline view:

    SJCAM M20 Car-Mode Battery Hack - test ride
    SJCAM M20 Car-Mode Battery Hack – test ride

    The battery icon instantly switches from “charging” to “desperately low” when the USB power drops, which is about what I expected, but the camera continues to record for about ten seconds before shutting down normally.

    The NP-BX1 battery in the holder comes from the batch of craptastic BatMax batteries with a depressed starting voltage. An actual new cell with a slightly higher voltage would keep the camera slightly happier during those last ten seconds, but … so far, so good.

    Another possibility would be a trio of 1.5 V bucked lithium AA cells, with the diode to prevent charging and minus the charger.

  • Garden Bypass

    Garden Bypass

    Mary had been thinking of blocking the narrow path between the neighbor’s fence and her garden, so I set up the trail camera to see what went on out there when we weren’t around.

    The Midnight Possum must have another appointment:

    IM_00003 - Midnight opossum - 2023-06-21
    IM_00003 – Midnight opossum – 2023-06-21

    Raccoons definitely use the path as a highway:

    IM_00013 - Early raccoon - 2023-06-28
    IM_00013 – Early raccoon – 2023-06-28

    And, as if we didn’t have enough deer already:

    Back yard deer - new fawn - 2023-06-24
    Back yard deer – new fawn – 2023-06-24

    My recommendation: don’t block the path, because we are badly outnumbered!

  • SJCam M50 Condensation

    SJCam M50 Condensation

    I put the camera in the front yard to monitor a new groundhog hole, then mowed the lawn. Although smoke drifting in from the Canadian fires has posed a problem, the air quality wasn’t this bad:

    SJCam M50 camera condensation - foggy image
    SJCam M50 camera condensation – foggy image

    It turns out the camera’s case seal isn’t quite up to the task:

    SJCam M50 camera condensation - detail
    SJCam M50 camera condensation – detail

    The lip around the front half of the case presses against a rubber gasket around the rear half, which means the water on the electronics chassis is inside the camera case:

    SJCam M50 camera condensation - case edge
    SJCam M50 camera condensation – case edge

    Fortunately, the water condensed on the inside of the glass lens protector, rather than on the camera itself:

    SJCam M50 camera condensation - interior
    SJCam M50 camera condensation – interior

    I let the whole thing dry out on the bench for a few days and all seems right again.

    The leak does make me think leaving it out in the rain is a Bad Idea™, which isn’t the sort of thought one should have about a trail camera.

    Diurnal pumping can explain many electronic failures. For the record, the monitoring station on the Walkway Over the Hudson vanished a while ago, probably due to rampant electronic corrosion.

  • Raccoons In the Night

    Raccoons In the Night

    The only reason we haven’t seen a standing raccoon is because we’re not awake when it happens:

    Raccoons vs wheelbarrow - 2023-06-09
    Raccoons vs wheelbarrow – 2023-06-09

    The glowing dot over on the far right is a third raccoon!

    They are athletic critters:

    Raccoons in wheelbarrow - 2023-06-09
    Raccoons in wheelbarrow – 2023-06-09

    Mary puts garden clippings in the wheelbarrow before hauling them over the hill to our organic dumping ground. Something must smell pretty good in there:

    Raccoons around wheelbarrow - 2023-06-09
    Raccoons around wheelbarrow – 2023-06-09

    The wire mesh over the new plantings in the garden seems to be holding them at bay, but it must come off before it snares the growing plants. We hope whatever is in the fertilizer will have worn off by then!

  • Copying Action Camera Video Files: Now With Arrays

    Copying Action Camera Video Files: Now With Arrays

    Using Bash arrays is an exercise in masochism, but I got to recycle most of the oddities from the previous script, so it wasn’t a dead loss.

    The cameras use individually unique / screwy / different filesystem layouts, so the script must have individual code to both copy the file and decapitalize the file extensions. This prevents using a single tidy function, although laying out the code in case statements keyed by the camera name helps identify what’s going on.

    My previous approach identified the MicroSD cards by their UUIDs, which worked perfectly right up until the camera reformats the card while recovering from a filesystem crash and installs a randomly generated UUID. Because there’s no practical way to modify an existing UUID on a VFAT drive, I’m switching to the volume label as needed:

    #-- action cameras and USB video storage
    UUID=B40C6DD40C6D9262	/mnt/video	ntfs	user,noauto,uid=ed	0	0
    UUID=B257-AE02		/mnt/Fly6	vfat	user,noauto,uid=ed	0	0
    #UUID=0000-0001		/mnt/M20	vfat	user,noauto,uid=ed	0	0
    UUID=3339-3338		/mnt/M20	vfat	user,noauto,uid=ed	0	0
    LABEL=AS30V		/mnt/AS30V	exfat	user,noauto,uid=ed	0	0
    LABEL=C100-0001		/mnt/C100_1	vfat	user,noauto,uid=ed	0	0
    LABEL=C100-0002		/mnt/C100_2	vfat	user,noauto,uid=ed	0	0
    UUID=0050-0001		/mnt/M50	vfat	user,noauto,uid=ed	0	0
    

    In particular, note the two UUIDs for the M20 camera: there’s a crash and reformat in between those two lines. The two C100 cameras started out with labels because the M20 taught me the error of my ways.

    The script simply iterates through a list array of the cameras and tries to mount the corresponding MicroSD card for each one: the mount points are cleverly chosen to match the camera names in the array. Should the mount succeeds, an asynchronous rsync then slurps the files onto the bulk video drive.

    With all the rsync operations running, the script waits for all of them to complete before continuing. I don’t see much point in trying to identify which rsync just finished and fix up its files while the others continue to run, so the script simply stalls in a loop until everything is finished.

    All in all, the script scratches my itch and, if naught else, can serve as a Bad Example™ of how to get the job done.

    A picture to keep WordPress from reminding me that readers respond positively to illustrated posts:

    A pleasant day for a ride - 2023-06-01
    A pleasant day for a ride – 2023-06-01

    Ride on!

    The Bash script as a GitHub Gist:

    #!/bin/bash
    # This uses too many bashisms for dash
    source /etc/os-release
    echo 'Running on' $PRETTY_NAME
    if [[ "$PRETTY_NAME" == *Manjaro* ]] ; then
    ren='perl-rename'
    dm='sudo dmesg'
    elif [[ "$PRETTY_NAME" == *Ubuntu* ]] ; then
    ren='rename'
    dm='dmesg'
    else
    echo 'New distro to me:' $PRETTY_NAME
    echo ' … which rename command is valid?'
    exit
    fi
    echo Check for good SD card spin-up
    $dm | tail -50
    echo … Ctrl-C to bail out and fix / Enter to proceed
    read junk
    thisdate=$(date –rfc-3339=date)
    echo Date: $thisdate
    # MicroSD / readers / USB drive defined in fstab
    # … with UUID or PARTID as appropriate
    echo Mounting bulk video drive
    sudo mount /mnt/video
    if [ $? -ne 0 ]; then
    echo '** Cannot mount video storage drive'
    exit
    fi
    # Show starting space available
    df -h /mnt/video
    # list the cameras
    declare -a cams=( AS30V Fly6 M20 M50 C100_1 C100_2 )
    declare -A targets=( \
    [AS30V]=/mnt/video/AS30V/$thisdate \
    [Fly6]=/mnt/video/Fly6/DCIM \
    [M20]=/mnt/video/M20/$thisdate \
    [M50]=/mnt/video/M50/$thisdate \
    [C100_1]=/mnt/video/C100_1/$thisdate \
    [C100_2]=/mnt/video/C100_2/$thisdate \
    )
    declare -A PIDs
    declare -A Copied
    echo Iterating through cameras: ${cams[*]}
    Running=0
    for cam in ${cams[*]} ; do
    printf "\nProcessing: $cam\n"
    mpt="/mnt/$cam"
    target=${targets[$cam]}
    sudo mount $mpt
    if [ $? -eq 0 ]; then
    echo " Start $cam transfer from $mpt"
    echo " Make target directory: $target"
    mkdir $target
    case $cam in
    ( AS30V )
    rsync -ahu –progress –exclude "*THM" $mpt/MP_ROOT/100ANV01/ $target &
    ;;
    ( Fly6 )
    rsync -ahu –progress $mpt /mnt/video &
    ;;
    ( M20 )
    n=$( ls $mpt/DCIM/Photo/* 2> /dev/null | wc -l )
    if [ $n -gt 0 ] ; then
    echo " copy M20 photos first"
    rsync -ahu –progress $mpt/DCIM/Photo/ $target
    fi
    echo " cmd: rsync -ahu –progress $mpt/DCIM/Movie/ $target"
    rsync -ahu –progress $mpt/DCIM/Movie/ $target &
    ;;
    ( M50 )
    n=$( ls $mpt/DCIM/PHOTO/* 2> /dev/null | wc -l )
    if [ $n -gt 0 ] ; then
    echo " copy M50 photos first"
    rsync -ahu –progress $mpt/DCIM/PHOTO/ $target
    fi
    rsync -ahu –progress $mpt/DCIM/MOVIE/ $target &
    ;;
    ( C100_1 | C100_2 )
    n=$( ls $mpt/DCIM/Photo/* 2> /dev/null | wc -l )
    if [ $n -gt 0 ] ; then
    echo " copy $cam photos first"
    rsync -ahu –progress $mpt/DCIM/Photo/ $target
    fi
    rsync -ahu –progress $mpt/DCIM/Movie/ $target &
    ;;
    ( * )
    printf "\n**** Did not find $cam in list!\n"
    ;;
    esac
    PIDs[$cam]=$!
    echo " PID for $cam: " "${PIDs[$cam]}"
    Copied[$cam]=1
    (( Running++ ))
    else
    echo " skipping $cam"
    Copied[$cam]=0
    fi
    done
    printf "\n—– Waiting for all rsync terminations\n"
    echo PIDs: "${PIDs[*]}"
    if [ $Running -eq 0 ] ; then
    echo No rsyncs started, force error
    rcsum=9999
    else
    rcsum=0
    while [ $Running -gt 0 ] ; do
    echo " waiting: $Running"
    wait -n -p PID
    rc=$?
    rcsum=$(( rcsum+$rc ))
    echo RC for $PID: $rc
    (( Running– ))
    done
    echo All rsyncs finished
    fi
    if [ $rcsum -eq 0 ] ; then
    echo '—– Final cleanups'
    for cam in ${cams[*]} ; do
    if [ "${Copied[$cam]}" -eq 1 ] ; then
    echo Cleanup for: $cam
    mpt=/mnt/$cam
    target=${targets[$cam]}
    echo Target dir: $target
    case $cam in
    ( Fly6 )
    find $target -name \*AVI -print0 | xargs -0 $ren -v -f 's/AVI/avi/'
    rm -rf $mpt/DCIM/*
    ;;
    ( AS30V )
    find $target -name \*MP4 -print0 | xargs -0 $ren -v -f 's/MP4/mp4/'
    rm $mpt/MP_ROOT/100ANV01/*
    ;;
    ( M50 )
    find $target -name \*MP4 -print0 | xargs -0 $ren -v -f 's/MP4/mp4/'
    rm $mpt/DCIM/MOVIE/*
    n=$( ls $mpt/DCIM/PHOTO/* 2> /dev/null | wc -l )
    if [ $n -gt 0 ] ; then
    echo placeholder $cam
    rm $mpt/DCIM/PHOTO/*
    fi
    ;;
    ( * )
    find $target -name \*MP4 -print0 | xargs -0 $ren -v -f 's/MP4/mp4/'
    find $target -name \*JPG -print0 | xargs -0 $ren -v -f 's/JPG/jpg/'
    rm $mpt/DCIM/Movie/*
    n=$( ls $mpt/DCIM/Photo/* 2> /dev/null | wc -l )
    if [ $n -gt 0 ] ; then
    echo placeholder $cam
    rm $mpt/DCIM/Photo/*
    fi
    ;;
    esac
    sudo umount $mpt
    else
    echo No cleanup for: $cam
    fi
    done
    echo '—– Space remaining on video drive'
    df -h /mnt/video
    sudo umount /mnt/video
    date
    echo Done!
    else
    echo Whoopsie! Total RC: $rcsum
    fi

  • Going About Their Daily Affairs

    Going About Their Daily Affairs

    The fox caught what looks like a small groundhog for supper:

    IM_00307 - Fox with supper - 2023-05-25
    IM_00307 – Fox with supper – 2023-05-25

    The tom turkeys have been forming and re-forming their groups:

    IM_00178 - Turkey parade - 2023-05-24
    IM_00178 – Turkey parade – 2023-05-24

    The gray cat may have spotted breakfast out there in the yard:

    IM_00112 - Gray Cat - 2023-05-23
    IM_00112 – Gray Cat – 2023-05-23

    We haven’t seen a raccoon stand up like this before, so something must be very interesting out there:

    IM_00089 - Standing raccoon - 2023-05-27
    IM_00089 – Standing raccoon – 2023-05-27

    Off to its far right, Mary had fertilized a new pepper planting, which evidently smelled good enough to motivate vigorous digging. None of the plants sustained damage, despite being tossed around, but dexterous paws were surely involved!

  • Chipmunk Sprint Speed

    Chipmunk Sprint Speed

    The trail camera caught a chipmunk with cheek pouches stuffed full of maple seeds:

    Chipmunk Run - 0042
    Chipmunk Run – 0042

    The critter evidently heard something, as it froze in position for some seconds, then launched toward its burrow somewhere on the left:

    Chipmunk Run - 0047
    Chipmunk Run – 0047

    Whatever it heard must have been terrifying:

    Chipmunk Run - 0053
    Chipmunk Run – 0053

    It covered 2 m across the camera field in 1/2 s (15 frames at 30 f/s) for an average speed of 4 m/s = 9 mph from launch.

    A slide show for your edification:

    • Chipmunk Run - 0042
    • Chipmunk Run - 0045
    • Chipmunk Run - 0047
    • Chipmunk Run - 0053
    • Chipmunk Run - 0058
    • Chipmunk Run - 0059
    • Chipmunk Run - 0060
    • Chipmunk Run - 0061
    • Chipmunk Run - 0062

    We know this chipmunk as “Stumpy”, because of its half-length tail, and think it has considerable motivation for outstanding speed.

    Tail high, little one!