Setting up Raspberry Pi Zero W with e-Ink hat

These are new to me, but here’s a brief document on setting them up. The Raspberry Pi Zero W:

Dimensions: 65mm × 30mm × 5mm

SoC Broadcom BCM2835
CPU ARM11 running at 1GHz
RAM 512MB
Wireless 2.4GHz 802.11n wireless LAN
Bluetooth Bluetooth Classic 4.1 and Bluetooth LE
Power 5V, supplied via micro USB connector
AV 1080P HD video & stereo audio via mini-HDMI connector

I got this kinda cool USB combo case that allows you to use it dual sided (!), that is either side can be inserted into the USB port for power, and in theory you can SSH in over USB:

I ran into trouble with the GPIO pin headers, they require soldering. I’d prefer… not… to solder so I bought these pressure mount GPIO pin headers instead

I got confused because the “regular” Pis have these headers already pre-soldered on, but apparently that’s not the case on the Pi Zero. EDIT: there is a distinction between the Pi Zero W and the Pi Zero WH – which has the headers pre-soldered. That’s what you want, if you need the headers!

So basically what you need is:

  • Pi Zero W (make sure it’s the 2017 wifi enabled model)
  • the “hammer” GPIO connector set that you can pressure mount on
  • quality 32gb SD card
1 Like

I do have these two pi-zeros set up and running:

The official way to set them up is via SSH over USB per the wiki:

https://wiki.52pi.com/index.php/USB_dongle_for_Raspberry_Pi_Zero/Zero_W_SKU:EP-0097

  • Download the latest Raspbian image 32-bit
  • Flash your SD card as usual
  • Open up the boot partition and edit config.txt, adding dtoverlay=dwc2 to the bottom
  • Open up cmdline.txt and add modules-load=dwc2,g_ether after rootwait
  • Create a new file named ssh in the boot folder
  • Insert this TF card to Raspberry Pi Zero/Zero W
  • Pop your newly set up SD card into your Pi Zero
  • plug it into a USB port and you should be able to SSH in to raspberrypi.local,
  • you will need Bonjour, iTunes or Quicktime installed in Windows or Avahi Daemon in Linux for this to work.

I couldn’t get the last bits to work in Windows 10, though I definitely made edits to the relevant files in the filesystem:

cmdline.txt

console=serial0,115200 console=tty1 root=PARTUUID=c2eb13c4-02 rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait modules-load=dwc2,g_ether

config.txt

# For more options and information see
# http://rpf.io/configtxt
# Some settings may impact device functionality. See link above for details

# uncomment if you get no picture on HDMI for a default "safe" mode
#hdmi_safe=1

# uncomment this if your display has a black border of unused pixels visible
# and your display can output without overscan
#disable_overscan=1

# uncomment the following to adjust overscan. Use positive numbers if console
# goes off screen, and negative if there is too much border
#overscan_left=16
#overscan_right=16
#overscan_top=16
#overscan_bottom=16

# uncomment to force a console size. By default it will be display's size minus
# overscan.
#framebuffer_width=1280
#framebuffer_height=720

# uncomment if hdmi display is not detected and composite is being output
#hdmi_force_hotplug=1

# uncomment to force a specific HDMI mode (this will force VGA)
#hdmi_group=1
#hdmi_mode=1

# uncomment to force a HDMI mode rather than DVI. This can make audio work in
# DMT (computer monitor) modes
#hdmi_drive=2

# uncomment to increase signal to HDMI, if you have interference, blanking, or
# no display
#config_hdmi_boost=4

# uncomment for composite PAL
#sdtv_mode=2

#uncomment to overclock the arm. 700 MHz is the default.
#arm_freq=800

# Uncomment some or all of these to enable the optional hardware interfaces
#dtparam=i2c_arm=on
#dtparam=i2s=on
#dtparam=spi=on

# Uncomment this to enable infrared communication.
#dtoverlay=gpio-ir,gpio_pin=17
#dtoverlay=gpio-ir-tx,gpio_pin=18

# Additional overlays and parameters are documented /boot/overlays/README

# Enable audio (loads snd_bcm2835)
dtparam=audio=on

[pi4]
# Enable DRM VC4 V3D driver on top of the dispmanx display stack
dtoverlay=vc4-fkms-v3d
max_framebuffers=2

[all]
#dtoverlay=vc4-fkms-v3d
dtoverlay=dwc2
dtparam=act_led_trigger=actpwr
gpu_mem=32

It says you will need Bonjour, iTunes or Quicktime installed in Windows or Avahi Daemon in Linux for this to work and I installed iTunes in Windows 10 but still had no luck getting in via local SSH… the raspberrypi.local address could not be resolved.

1 Like

What I did get to work is setting up wifi access. Create a blank text file named wpa_supplicant.conf. Use a plain text editor rather than a Word Processor.

wpa_supplicant.conf

country=us
update_config=1
ctrl_interface=/var/run/wpa_supplicant

network={
 scan_ssid=1
 ssid="MyNetworkSSID"
 psk="Pa55w0rd1234"
}

(Oh and I also created the blank ssh file in the root so SSH was enabled.)

I copied that wpa_supplicant.conf file to the SD card in the root, plugged in the USB power, let it boot up, and voila… it showed up with a valid IP address:

1 Like

There’s also a pretty good list of raspi-config things you want to do (such as set a unique hostname) documented here:

1 Like

I got a pressure mount hat from here, because I suuuck at soldering.

Pressure mounting is a bit finicky so you have to eyeball it and make sure all the pins are more or less at the same depth.

(I also belatedly realized the Raspberry Pi Zero WH includes the soldered-on headers for a few more bucks, $18 vs $27, I should have just done that in the first place! I also noticed this stuff is a bit more expensive on Amazon versus the “official” vendors like Canakit)

The e-ink display docs are here, and they work. I skipped the Python 2 stuff though.

https://www.waveshare.com/wiki/2.13inch_e-Paper_HAT_(B)?Amazon

(click on “hardware / software setup” tab at the top, scroll down to the Raspberry Pi section)

This e-Ink module is marked V3, rev 2.1, and I think 4 line SPI?

so the example python file I used included V3 as well as the dimensions of 2.13 inch. After some pressure mount pin nudging, I got both to work!

1 Like

Pins, pins, pins!

Fun interactive diagram of the pinout

https://pinout.xyz/

Note that the square pin is always pin #1!

1 Like

If you had bet me a thousand dollars when I woke up this morning that I’d be reading the sentence

I installed iTunes in Windows 10 but still had no luck getting in via local SSH

I would have called you a fool and taken it gladly. (How on earth is Bonjour/iTunes providing USB/serial SSH? And surely there has to be a non-Apple solution for that problem… right?)

ETA: also, I just did my own Pi setup this weekend with an old 3B I had lying around, turned it into a custom DHCP server so I could feed Smart DNS settings to my Rokus. What’s your plan with the e-ink displays? They look really neat!

2 Likes

Neat e-ink screen!

Try raspberrypi.lan instead of raspberrypi.local - that worked for me for SSH from Win 10 to a Pi3 with Raspberry Pi OS last month.

2 Likes

Hey! Thanks for the nudge! That did work! :partying_face:

I used Powershell this time, and note that I changed the name (via raspi-config) of each so that I could keep track of them:

  • pizero-a
  • pizero-b
PS C:\Users\jatwo> ping pizero-a.lan

Pinging pizero-a.lan [2600:1700:a410:2950:cca:c9f4:3a7f:3bb9] with 32 bytes of data:
Reply from 2600:1700:a410:2950:cca:c9f4:3a7f:3bb9: time=7ms
Reply from 2600:1700:a410:2950:cca:c9f4:3a7f:3bb9: time=11ms
Reply from 2600:1700:a410:2950:cca:c9f4:3a7f:3bb9: time=10ms
Reply from 2600:1700:a410:2950:cca:c9f4:3a7f:3bb9: time=12ms

Ping statistics for 2600:1700:a410:2950:cca:c9f4:3a7f:3bb9:
    Packets: Sent = 4, Received = 4, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
    Minimum = 7ms, Maximum = 12ms, Average = 10ms
PS C:\Users\jatwo>
PS C:\Users\jatwo> ssh pi@pizero-a.lan
pi@pizero-a.lan's password:
Linux pizero-a 5.4.83+ #1379 Mon Dec 14 13:06:05 GMT 2020 armv6l

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
Last login: Sat Jan 16 00:48:08 2021 from 2600:1700:a410:2950:bdd2:358d:6a21:fc4c
pi@pizero-a:~ $ echo yay
yay

I have no idea why @thw0rted but the docs page said iTunes might be required (Bonjour?). What can I say, I was desperate… I’ll uninstall that now…

2 Likes

Here’s what running the correct sample looks like. This is a V3 device (per the sticker) with a 2.13in screen, so epd_2in13b_V3_test.py it is!

root@pizero-a:/home/pi/e-Paper/RaspberryPi_JetsonNano/python/examples# python3 epd_2in13b_V3_test.py
INFO:root:epd2in13b_V3 Demo
INFO:root:init and Clear
DEBUG:root:e-Paper busy
DEBUG:root:e-Paper busy release
DEBUG:root:e-Paper busy
DEBUG:root:e-Paper busy release
INFO:root:Drawing
INFO:root:1.Drawing on the Horizontal image...
DEBUG:root:Horizontal
DEBUG:root:Horizontal
DEBUG:root:e-Paper busy
DEBUG:root:e-Paper busy release
INFO:root:2.Drawing on the Vertical image...
DEBUG:root:Vertical
DEBUG:root:Vertical
DEBUG:root:e-Paper busy
DEBUG:root:e-Paper busy release
DEBUG:root:Horizontal
DEBUG:root:Horizontal
DEBUG:root:e-Paper busy
DEBUG:root:e-Paper busy release
DEBUG:root:Horizontal
DEBUG:root:Horizontal
DEBUG:root:e-Paper busy
DEBUG:root:e-Paper busy release
INFO:root:Clear...
DEBUG:root:e-Paper busy
DEBUG:root:e-Paper busy release
DEBUG:root:e-Paper busy
DEBUG:root:e-Paper busy release
INFO:root:Goto Sleep...
DEBUG:root:e-Paper busy
DEBUG:root:e-Paper busy release
DEBUG:root:spi end
DEBUG:root:close 5V, Module enters 0 power consumption ...
root@pizero-a:/home/pi/e-Paper/RaspberryPi_JetsonNano/python/examples#

Here’s the epd_2in13b_V3_test.py code, also mirrored on github

#!/usr/bin/python
# -*- coding:utf-8 -*-
import sys
import os
picdir = os.path.join(os.path.dirname(os.path.dirname(os.path.realpath(__file__))), 'pic')
libdir = os.path.join(os.path.dirname(os.path.dirname(os.path.realpath(__file__))), 'lib')
if os.path.exists(libdir):
    sys.path.append(libdir)

import logging
from waveshare_epd import epd2in13b_V3
import time
from PIL import Image,ImageDraw,ImageFont
import traceback

logging.basicConfig(level=logging.DEBUG)

try:
    logging.info("epd2in13b_V3 Demo")
    
    epd = epd2in13b_V3.EPD()
    logging.info("init and Clear")
    epd.init()
    epd.Clear()
    time.sleep(1)
    
    # Drawing on the image
    logging.info("Drawing")    
    font20 = ImageFont.truetype(os.path.join(picdir, 'Font.ttc'), 20)
    font18 = ImageFont.truetype(os.path.join(picdir, 'Font.ttc'), 18)
    
    # Drawing on the Horizontal image
    logging.info("1.Drawing on the Horizontal image...") 
    HBlackimage = Image.new('1', (epd.height, epd.width), 255)  # 298*126
    HRYimage = Image.new('1', (epd.height, epd.width), 255)  # 298*126  ryimage: red or yellow image  
    drawblack = ImageDraw.Draw(HBlackimage)
    drawry = ImageDraw.Draw(HRYimage)
    drawblack.text((10, 0), 'hello world', font = font20, fill = 0)
    drawblack.text((10, 20), '2.13inch e-Paper bc', font = font20, fill = 0)
    drawblack.text((120, 0), u'微雪电子', font = font20, fill = 0)    
    drawblack.line((20, 50, 70, 100), fill = 0)
    drawblack.line((70, 50, 20, 100), fill = 0)
    drawblack.rectangle((20, 50, 70, 100), outline = 0)    
    drawry.line((165, 50, 165, 100), fill = 0)
    drawry.line((140, 75, 190, 75), fill = 0)
    drawry.arc((140, 50, 190, 100), 0, 360, fill = 0)
    drawry.rectangle((80, 50, 130, 100), fill = 0)
    drawry.chord((85, 55, 125, 95), 0, 360, fill =1)
    epd.display(epd.getbuffer(HBlackimage), epd.getbuffer(HRYimage))
    time.sleep(2)
    
    # Drawing on the Vertical image
    logging.info("2.Drawing on the Vertical image...")
    LBlackimage = Image.new('1', (epd.width, epd.height), 255)  # 126*298
    LRYimage = Image.new('1', (epd.width, epd.height), 255)  # 126*298
    drawblack = ImageDraw.Draw(LBlackimage)
    drawry = ImageDraw.Draw(LRYimage)
    drawblack.text((2, 0), 'hello world', font = font18, fill = 0)
    drawblack.text((2, 20), '2.13 epd b', font = font18, fill = 0)
    drawblack.text((20, 50), u'微雪电子', font = font18, fill = 0)
    drawblack.line((10, 90, 60, 140), fill = 0)
    drawblack.line((60, 90, 10, 140), fill = 0)
    drawblack.rectangle((10, 90, 60, 140), outline = 0)
    drawry.rectangle((10, 150, 60, 200), fill = 0)
    drawry.arc((15, 95, 55, 135), 0, 360, fill = 0)
    drawry.chord((15, 155, 55, 195), 0, 360, fill =1)
    epd.display(epd.getbuffer(LBlackimage), epd.getbuffer(LRYimage))
    time.sleep(2)
    
    # logging.info("3.read bmp file")
    Blackimage = Image.open(os.path.join(picdir, '2in13bc-b.bmp'))
    RYimage = Image.open(os.path.join(picdir, '2in13bc-ry.bmp'))
    epd.display(epd.getbuffer(Blackimage), epd.getbuffer(RYimage))
    time.sleep(2)
    
    # logging.info("4.read bmp file on window")
    blackimage1 = Image.new('1', (epd.height, epd.width), 255)  # 298*126
    redimage1 = Image.new('1', (epd.height, epd.width), 255)  # 298*126    
    newimage = Image.open(os.path.join(picdir, '100x100.bmp'))
    blackimage1.paste(newimage, (0,0))
    epd.display(epd.getbuffer(blackimage1), epd.getbuffer(redimage1))
    
    logging.info("Clear...")
    epd.init()
    epd.Clear()
    
    logging.info("Goto Sleep...")
    epd.sleep()
    time.sleep(3)
    epd.Dev_exit()
        
except IOError as e:
    logging.info(e)
    
except KeyboardInterrupt:    
    logging.info("ctrl + c:")
    epd2in13b_V3.epdconfig.module_exit()
    exit()
1 Like