2020 has allowed me a small amount of “hobby” time. I’ve been contemplating a remote IoT device for sending pictures from our allotment, specifically of my apiary. This is part learning exercise, part “what is going on on the plot/apiary”.
I defined the following requirements:
- Solar-powered – there is no power on the site so this is the only reliable source
- Battery-backed – Needs to be able to smooth out issues supplying power to the device
- Very-low-power SoC device – Sheffield does not get much sun, especially in winter
- Camera
- 3G GSM modem compatible – needs to be able to connect to the internet!
- Operating System with low disk usage, preferably booting to RAM
I ultimately arrived at the following:
- Sunstore 6v 10w solar panel
- PiJuice Zero 1200Mah battery
- Raspberry Pi Zero (I got the W version but this is actually not required)
- ZeroCam Camera
- PiJuice Zero – power platform
- Globetrotter HSUPA Modem (icon 411 aka “Vodafone K3760”) – unlocked to all networks
- Tesco Mobile SIM
- PiCore / Tiny Core Linux OS
- 32G Micro SD Card
The choice of Tiny Core was driven largely because it boots to RAM. The documentation is patchy and getting it working consisted of lots of googling the forums. However the project does seem to be active with frequent recent releases.
Hardware
I had to solder the Pi Zero with a 40 pin header. I got some bread boards for practice and when I was happy enough I went for it. Fairly happy with the result.

The ZeroCam is really fiddly to insert and not something you want to repeat on a regular basis. Also the screws to connect the PiJuice Zero HAT to the Pi Zero are not great and one thread was stripped with ease so its missing – see below.
Here’s how things look at the moment.

Things to note:
- The LiPo battery incorrectly reported 246 degrees C (!) so hit a temperature violation and therefore doesn’t charge. Disabling Temperature Sense in the software resolved this.
- The USB splitter is temporary for console access. I am using a micro USB to Ethernet adapter for testing at my desk whilst I await the SIM (and so as to not consume data over 3G unnecessarily).
- The HDMI stuff will obviously go once in the field.
- There is no case. I’m probably going to use a clear plastic food container with the click down sides, drill a small hole for the camera and then stick some silica gel sachets inside.
Software
There are three elements to this:
- PiCore – The OS running on the Pi Zero
- The PiJuice control software
- Website backend software to receive and display the uploaded images.
Installing PiCore requires some manual steps:
- Download and extract the image from http://tinycorelinux.net/12.x/armv6/releases/RPi/
- Write the img file to the sdcard – I have a USB-C card reader and used Image Writer
- Extend the second partition, doing something like:
1) Start fdisk partitioning tool as root:
sudo fdisk -u /dev/mmcblk0
Now list partitions with 'p' command and write down the starting and
ending sectors of the second partition.
2) Delete second partition with 'd' than recreate it with 'n' command.
Use the same starting sector as deleted had and provide end
sectore or size greater than deleted had having enough free space
for Mounted Mode. When finished, exit fdisk with 'w' command. Now
partition size increased but file system size is not yet changed.
3) Reboot piCore. It is necessary to make Kernel aware of changes.
4) After reboot expand file system to the new partition boundaries with
typing the following command as root:
resize2fs /dev/mmcblk0p2
Now you are ready to use the bigger partition.
I needed to install additional software packages. These are squashfs images as TCZ’s. However out of the box, there is no support for USB ethernet or wifi. I therefore remounted the card and copied these modules manually onto the sd card, before rebooting the Pi and loading the modules.
tce-load -i /mnt/mmcblk0p2/tce/optional/net-usb-5.4.51-piCore.tcz
I was then able to load the remaining modules I need going forward:
tc@box:~$ cat /mnt/mmcblk0p2/tce/onboot.lst
openssh.tcz
my-modules.tcz
ffmpeg.tcz
net-usb-5.4.51-piCore.tcz
kmaps.tcz
ppp.tcz
ppp-modules-5.4.51-piCore.tcz
usb-serial-5.4.51-piCore.tcz
curl.tcz
ntp.tcz
I also needed to create a custom squashfs kernel module package – listed above as my-modules.tcz – this is for ffmpeg support to enable the camera. In the end I took the lazy option and just grabbed staging/ and media/ from the complete modules tarball.
tce-load -wi squashfs-tools
mkdir my-modules
mkdir -p my-modules/lib/modules/5.4.51-piCore/kernel/drivers/
cp -r drivers/staging/ my-modules/lib/modules/5.4.51-piCore/kernel/drivers/
cp -r drivers/media/ my-modules/lib/modules/5.4.51-piCore/kernel/drivers/
mksquashfs my-modules/ my-modules.tcz
sudo cp my-modules.tcz /mnt/mmcblk0p2/tce/optional/
You also need to mount the first partition and configure config.txt file to ensure the camera loads on boot:
tc@box:~$ mount /mnt/mmcblk0p1/
tc@box:~$ tail -n 6 /mnt/mmcblk0p1/config.txt
[all]
#dtoverlay=vc4-fkms-v3d
#Enable camera
start_x=1
gpu_mem=128
disable_camera_led=1
My startup script looks something like this:
date # debugging for RTC, will drop once figured this out
sleep 5
ifconfig eth0 up # manually bring up interface
udhcpc -i eth0 # get an address
sleep 5 # wait for a bit before trying to get the time
ntpdate -s time.nist.gov
date # this should be the correct date now
loadkmap < /usr/share/kmap/qwerty/uk.kmap # load the UK keyboard map
TIMENOW=$(date +%Y-%m-%dT%H:%M:%S) # format the date to something WordPress will accept
# ffmpeg is a bit noisy so add some flags to quieten it down
ffmpeg -i /dev/video0 -frames:v 1 /home/tc/$TIMENOW.jpg -hide_banner -loglevel panic -y
METADATA="A picture taken at $TIMENOW" # A string for adding some basic text
# WordPress accepts images then you can apply metadata to that image so do some nasty awk to get the ID returned. Yes there are better ways to do this.
IMG_ID=`curl -sk --request POST \
--url https://grumpybeeman.com/wp-json/wp/v2/media \
--header "cache-control: no-cache" \
--header "content-disposition: attachment; filename=$TIMENOW.jpg" \
--user username:redacted_application_password \
--header "content-type: image/jpg" \
--data-binary "@/home/tc/$TIMENOW.jpg" \
--location | awk -F : '{ print $2 }' | cut -f1 -d","`
# Now we grab the IP address. The idea is that the images will have this as the description so I can access the pi remotely if I need to. How this will actually work in practice is anyone's guess.
IP_ADDR=`ifconfig eth0 | grep inet | awk -F : '{ print $2 }' | cut -f1 -d " "`
curl -sk --request POST \
--url https://grumpybeeman.com/wp-json/wp/v2/media/$IMG_ID \
--user username:redacted_application_password \
--header "content-type: application/json" \
-d '{"title":"'"$METADATA"'", "caption":"'"$METADATA"'", "description":"'"$IP_ADDR"'", "alt_text":"'"$METADATA"'", "date":"'"$TIMENOW"'"}'
# I can toggle this file between 1 and 0 to control whether the Pi turns off immediately after taking the picture or not. If its on then I can shell in and kill the poweroff process before it completes.
POWER=$(curl https://grumpybeeman.com/control)
if [ $POWER == 1 ]; then
poweroff -d 300
elif [ $POWER == 0 ]; then
poweroff
else
poweroff -d 60 # handle errors
fi
At each change, PiCore requires you to run:
filetool.sh -b
This persists changes to the disk.
The second part of this blog will be wiring in the solar panel, moving to GSM connectivity and initial field trials!