Breadboarding with a Raspberry Pi Zero W - Headless, USB tethered - Page 1
Forum section: electronics / projects

author: Ian.M
author_rank: Super Contributor
timestamp: April 05, 2018, 03:54:20 pm
content: Some ramblings and jottings on my experiences with running a Pi headless, tethered to a Windows PC, and breadboarding with it.Rationale - Why headless?I don't have a fancy monitor with DVI or TV with HDMI and I wanted a low cost setup for experimenting with Pi interfacing so I decided to get a Raspberry Pi Zero W and run it headless from my Windows XP netbook. Due to the legacy windows OS, and my dislike of WiFi for home networks, I ran into various issues along the way.1. Choice of hardwareFor breadboarding I wanted a cheap and simple hookup with the minimum number of cables. As USB OTG support for the Pi Zero (a.k.a. USB Gadget mode) has been available in the Rasbian kernel since mid 2016, a Pi Zero or Zero W (or Compute Module or even a model A) can be networked to a PC by USB, appearing as a RNDIS adaptor to the PC. You cant use any PI with on-board Ethernet or multiple USB 'A' sockets, as the on-board USB hub /Ethernet controlled chip blocks device mode access to the BCM283x SoC's USB port. A plain Pi Zero wouldn't be able to access any network except through the host PC, so I bought a PI Zero W with onboard WiFi and Bluetooth.The Bluetooth is both a blessing and a curse as it uses the BCM2835's main PL011 hardware UART and the auxiliary mini-UART that is normally routed to the TX and RX pins on the expansion header doesn't have a proper baud rate generator so its speed varies with the CPU clock, making it essentially unusable unless you either clock down the CPU and lock its speed, slugging performance, or disable the Bluetooth in config.txt so the main UART can be rerouted to the expansion header before the kernal loads.Other hardware choices included a Cyntech Split+ to get the expansion header into the breadboard and a 16Gb Micro-SD card that had originally come with a PI 3 B with NOOBS on it, and a K&H AD-12 breadboard. I replaced the Split+'s ribbon cable with a shorter one that also has a male 40 pin IDC header crimped to it so I can still plug in pHATs when breadboarding.2. Initial SetupAfter some research I found that NOOBS would be of very little benefit to a headless Pi as its controlled by direct local interaction. Apparently you can control NOOBS by VNC, but then you probably will still have issues configuring the OS(es) installed by NOOBS for headless operation. I therefore decided to go straight to a fresh Rasbian Stretch image.Raspberrypi.org's recommended one-step imaging tool - Etcher - doesn't run on XP, so, rather than firing up a Linux VM, I decided to grab the seperate tools I needed and do it manually. To install Rasbian, you need to write the image to a FAT32 formatted SD card. The native Windows formatter is best avoided, so I grabbed the SD Association's SD Memory Card Formatter. Unfortunately v5.0 doesn't work on XP and all the links to their site for v4.0 redirect to v5.0, so I had to get v4.0 from a 3rd party website. I also had to prepare a 64Gb SD card for the Pi 3B I'd nicked the 16Gb card from, but above 32Gb, the SD Memory Card Formatter will use exFAT (as will the native Windows formatter) so I grabbed a FAT32 formatter for large drives fromhttp://www.ridgecrop.demon.co.uk/guiformat.htm.Raspberrypi.org's recommended image writer for Windows if you cant/wont use Etcher is Win32DiskImager - you need v0.9 for XP and Vista. Everyone else can use the current version.I grabbed the current full Rasbian Stretch image, not the light one as I wanted to be able to VNC into the Pi.I also had to update my 7ZIP installation to handle the ZIP64 format zipped Rasbian image from Raspberrypi.org.After unpacking the image and writing it to a freshly formatted SD card, you need to patch some stuff to bring a Pi up headless without a logic level UART cable hooked to the expansion header. Many of the headless Pi guides are over-complex (due to the perceived need to configure WiFi) or plain out of date.The key things thst one needs to do are to configure the Pi to enable it to run as a NDIS gadget and enable SSH access to it so you can still get in if X-Windows is borked or if there is a problem with the VNC server. SSH access used to be enabled by default, but with the introduction of on-board WiFi, it was decided that was an unacceptable risk so you now have to enable it by creating an empty file calledSSH(with no extension) in the root of the boot partition of the SD card. Rasbian 'eats' the SSH file so don't be surprised that it vanishes after its done its job.You also need a SSH capable terminal program on the PC. I'm using puTTY.To configure the Pi for USB RNDIS networking, you need to edit two files in the root of the boot partition. The first iscmdline.txtwhich is read very early in the boot process by the GPU and is used to configure the SoC's I/O and CPU. It needsmodules-load=dwc2,g_etheradded afterrootwait, but you have to be a bit careful as cmdline.txt options are all on one line, separated by a single space, there are absolutely no spaces within each option and the line doesn't have a linefeed or newline at the end of it. Also, its desirable to set the RNDIS host and slave MAC addresses, so they don't randomly change on each boot, so your PC sees it as the same network adapter, and your DNS server can give the Pi a stable IP address.Code:modules-load=dwc2,g_ether g_ether.host_addr=b8:27:eb:00:00:00 g_ether.dev_addr=b8:27:eb:ff:ff:ffIf you have multiple tethered Pis, use unique MAC addresses for each!b8:27:ebis the OUI (MAC address prefix) for the Raspberry Pi Foundation. There is an infinitesimal risk of collision with real Ethernet equipped Pis, but hopefully low addresses were used 'in house' and high ones may not have been fully used before production switched to one of the Raspberry Pi Ltd OUIs.The other is config.txt, which is a fairly normal ini file with lots ofparameter=valuelines. It (fresh out the box) doesn't use sections and uses # for comments. You need to add a line readingCode:dtoverlay=dwc2at the end of it to enable 'Gadget' mode.*** Still editing below this line ***Todo (writeup):Configuring the Pi over SSHSetting desktop size for VNCGetting started with Python and Hardware interfacingInstalling Python on the PC and accessing Pi I/O pins remotelyHeadless over Bluetooth - is it more trouble than its worth?Adventures in misconfiguring SAMBA, MS networking and firewalls!<knocking off for now - I'll add more later>

author: Ian.M
author_rank: Super Contributor
timestamp: April 05, 2018, 03:55:05 pm
content: Here's a couple of Python 3 scripts I've been playing with. Both use thepigpio libraryfor I/O, so don't need to be SUDOed to elevate their rights,This one sends Morse code, outputting to a LED on one GPIO pin and a small speaker driven by a transistor from another GPIO pin.Code:#!/usr/bin/env python# Sends a string in Morse code on a flashing LED (active high) on BCM GPIO 25# and drives a speaker (via a transistor) on BCM GPIO 19 @ 1.8KHz.# modified to use pigpioimport pigpioimport time# Hardware settings:PWMpin=18 # Software PWM - sounds like sh!tLEDpin=25 # free choiceOff=pigpio.LOW # Active highOn=pigpio.HIGHFREQ=800 # beeper frequencyVOL=63 # Volume 0-127# Software settings:wpm=20 # Morse speed# Text string to sends='He was going to the Commander to explain this to him, and he was hoping to get ''his approval to use any means necessary to get the kid\'s head on straight. ''Because if he didn\'t give the so called genius a much needed wake up call ''in the safety of the base, it would happen outside on a mission and the ''poor fool might not survive.'# ITU Morse## short mark, dot or 'dit' '.' is one unit long# longer mark, dash or 'dah' '-' is three units long# intra-character gap (between the dots and dashes within a character) is one unit long# short gap (between letters) is three units long# medium gap (between words) is seven units long# Morse code tablemorse={"'" :'.----.', # Apostrophe'"' : '.-..-.', # Inverted commas (quotation marks)'-' : '-....-', # Hyphen or dash or subtraction sign'(' : '-.--.', # Left-hand bracket (parenthesis)')' : '-.--.-', # Right-hand bracket (parenthesis)',' : '--..--', # Comma'.' : '.-.-.-', # Full stop (period)'/' : '-..-.', # Fraction bar or division sign':' : '---...', # Colon or division sign'?' : '..--..', # Question mark'@' : '.--.-.', # Commercial at'+' : '.-.-.', # Cross or addition sign'=' : '-...-', # Double hyphen'*' : '-..-', # Multiplication sign'0' : '-----','1' : '.----','2' : '..---','3' : '...--','4' : '....-','5' : '.....','6' : '-....','7' : '--...','8' : '---..','9' : '----.','a' : '.-','b' : '-...','c' : '-.-.','d' : '-..','e' : '.','f' : '..-.','g' : '--.','h' : '....','i' : '..','j' : '.---','k' : '-.-','l' : '.-..','m' : '--','n' : '-.','o' : '---','p' : '.--.','q' : '--.-','r' : '.-.','s' : '...','t' : '-','u' : '..-','v' : '...-','w' : '.--','x' : '-..-','y' : '-.--','z' : '--..',' ' : ' ', # 7 unit gap - see above. Each ' ' in code is a 2 unit gap# as each element is followed by a one unit gap, 3*' '=7 units'Understood' : '...-.','Error' : '........', # May need special handling, only 8 stroke code'Invitation to transmit' : '-.-','Wait' : '.-...','End of work' : '...-.-','Starting signal' : '-.-.-', # To precede every transmission}for c in range(ord('a'),ord('z')): # Duplicate lower case to upper casemorse[chr(c).upper()]=morse[chr(c)]# convert ASCII string to morse symbols. Unknown codes mapped to Error code.m=''for c in s:m=m+morse.get(c,morse['Error'])+' 'try: # catch exceptions to cleanup on exitpi = pigpio.pi() # open local pigpioif not pi.connected: # exit script if no connectionexit()pi.set_mode(LEDpin, pigpio.OUTPUT) # LED output from pin LEDpinpi.write(LEDpin, Off)pi.set_mode(PWMpin,pigpio.OUTPUT) # initialize pin PWMpin as an output for PWMpi.set_PWM_frequency(PWMpin,FREQ) #set pin PWMpin as PWM output, with 2KHz frequencypi.set_PWM_dutycycle(PWMpin,0) # make sure its off to starttime.sleep(1)u=60/(50*wpm) # timing based on 'PARIS' WPMfor c in m: # loop through morse symbols to sendif c=='.': # send 'dit'pi.write(LEDpin, On)pi.set_PWM_dutycycle(PWMpin,VOL)time.sleep(u)pi.write(LEDpin, Off)pi.set_PWM_dutycycle(PWMpin,0)if c=='-': #send 'dah'pi.write(LEDpin, On)pi.set_PWM_dutycycle(PWMpin,VOL)time.sleep(3*u)pi.write(LEDpin, Off)pi.set_PWM_dutycycle(PWMpin,0)if c==' ': # 3u gap between characterstime.sleep(u) # already has 1u from previous symbol and will have 1u added belowtime.sleep(u) # add 1u gap to all symbolsexcept KeyboardInterrupt:print("Execution interrupted (KeyboardInterrupt) . . .")finally: # On exit ...print("Cleanup on Exit . . .")# clean up pinspi.write(LEDpin, pigpio.LOW)pi.set_mode(LEDpin, pigpio.INPUT) # disable LED outputpi.set_PWM_dutycycle(PWMpin,0)pi.set_mode(PWMpin,pigpio.INPUT) # disable PWM pinprint("GPIO pins released")pi.stop() # Close pigpioprint("PIGPIO closed")print("==== DONE ====")I also have been testing a MCP23017 16 bit I2C I/O expanderCode:#!/usr/bin/env python# Output a byte on a MCP23017 16 bit I2C I/O expander use pigpioimport pigpioimport time# MCP23017 regs in unbanked modeIODIRA=0x00IODIRB=0x01IPOLA=0x02IPOLB=0x03GPINTENA=0x04GPINTENB=0x05DEFVALA=0x06DEFVALB=0x07INTCONA=0x08INTCONB=0x09IOCONA=0x0AIOCONB=0x0BGPPUA=0x0CGPPUB=0x0DINTFA=0x0EINTFB=0x0FINTCAPA=0x10INTCAPB=0x11GPIOA=0x12GPIOB=0x13OLATA=0x14OLATB=0x15# MCP23017 regs in banked modebIODIRA=0x00bIPOLA=0x01bGPINTENA=0x02bDEFVALA=0x03bINTCONA=0x04bIOCONA=0x05bGPPUA=0x06bINTFA=0x07bINTCAPA=0x08bGPIOA=0x09bOLATA=0x0AbIODIRB=0x10bIPOLB=0x11bGPINTENB=0x12bDEFVALB=0x13bINTCONB=0x14bIOCONB=0x15bGPPUB=0x16bINTFB=0x17bINTCAPB=0x18bGPIOB=0x19bOLATB=0x1A# IOCON bitmasksBANK=(1<<7)MIRROR=(1<<6)SEQOP=(1<<5)DISSLW=(1<<4)# HAEN=(1<<3)ODR=(1<<2)INTPOL=(1<<1)MCP23017POR=[0xFF,0xFF,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] # POR defaults in unbanked ordertry: # catch exceptions to cleanup on exitpi = pigpio.pi() # open local pigpioif not pi.connected: # exit script if no connectionexit()h = pi.i2c_open(1, 0x20) # open handle for MCP23017 at default address# Initialise MCP23017 for applicationpi.i2c_write_byte_data(h, bIOCONA, 0x00) # leave banked mode if in itpi.i2c_write_byte_data(h, IOCONA, (SEQOP|MIRROR|ODR) ) # set IOCON modepi.i2c_write_byte_data(h, IODIRA, 0xFF) # set port A to all inputspi.i2c_write_byte_data(h, GPPUA, 0xFF) # with weak pullupspi.i2c_write_byte_data(h, OLATB, 0xFF) # set port B latch to all '1'pi.i2c_write_byte_data(h, IODIRB, 0x00) # set port B to all outputswhile True: #forever loopd= pi.i2c_read_byte_data(h, GPIOA)# true data for 0.3 secondpi.i2c_write_byte_data(h, OLATB,d)time.sleep(0.3)# inverted data for 0.1 secondpi.i2c_write_byte_data(h, OLATB,d^0xFF)time.sleep(0.1)finally: # On exit ...print("Execution interrupted . . .")# clean up MCP23017 pins etc.pi.i2c_write_byte_data(h, bIOCONA, 0x00) # leave banked modepi.i2c_write_byte_data(h, IOCONA, 0x00) # set default IOCONpi.i2c_write_block_data(h, 0x00, MCP23017POR) # restore power on defaultsprint("MCP23017 reset")pi.i2c_close(h) # Close MCP23017 handleprint("MCP23017 closed")pi.stop() # Close pigpioprint("PIGPIO closed")print("==== DONE ====")As the Pigpio library connects via TCP/IP to the pigpiod daemon to handle the actual I/O, you can run them over your LAN controlling the pins of a remote Pi. You don't even have to run them on a Pi - I've run them with no changes using Python 3.4.4 under Windows XP on the netbook. The only things I had to do were to configure the Pi for remote GPIO access,pip install pigpioon the PC and also set up a Windows system environment variablePIGPIO_ADDR=ians-pi-0w.mshome.netwhich tells PIGPIO where on the LAN to find the default pigpiod daemon to connect to.

author: Ian.M
author_rank: Super Contributor
timestamp: April 05, 2018, 03:57:02 pm
content: Ciseco Slice of Pi/O MCP23017 I2C 16 bit I/O expander breakout boardsThis was probably the board that originally popularised the MCP23017 as the favourite I/O expander of the R.Pi community. Good documentation is extremely scattered as Ciseco were acquired by '365 Agile' back in 2015, and they killed Ciseco off mid 2016, so the only resources for the official documentation are the Internet Archive which doesn't have any of their PDFs, scattered PDFs that various users have reposted, and some stuff on GitHub. There are still some available N.O.S. - I suspect a lot of people have ignored it once the Pi B+ introduced the 40 pin header.After some shenanigans with my router which had dropped the fixed IP for the PC with the Hi-Rez SCSI scanner, and as a result it had hopped to an IP I hadn't whitelisted for file sharing in the firewall, I finally got the scans of the PCB done and transferred to my usual PC.If you build the board as-is, you get 16 I/O pins and 16 grounds, which for many applications is a few grounds too many! I've modded the board to break out INTA, INTB, and Vcc to pins on one of the eight pin ground headers, with three each for Vcc and Gnd. That's far handier for breadboarding. However the mod needs some top-side track cuts under the header so it would be a PITA to apply if you've already built the board.The upper ground header (by Port A) has multiple connections to the ground plane, so is best ignored - I didn't even fit it. The lower ground header (by port B) is the best candidate for modding as it only needs four cuts to isolate a section of it. The bottom two pins have extra tracks to the ground plane so I allocated the bottom three as Ground so I didn't have to deal with them. I grabbed the Xacto knife and eight cuts later I had three pins in the middle isolated for Vcc and the top two pins individually isolated for INTA and INTB (cuts marked in purple in attached image). The cuts were checked by holding the board up to a bright light to be certain there were no whiskers of copper remaining.However that left part of the ground plane and the bottom three Grounds on header hanging by a thread-like track along the board edge, so I scraped a couple of spots to link the ground plane up again, and ran a patch wire (black wire bottom left). That left three wires to run pin to pin, checking for shorts as I did so. It would be slightly easier to do so before soldering the socket and header, but I did it afterwards. The header got a laminated label with the new pin functions, (which probably took longer to get the right size than modding the board did), and that's it, job done, success!The bottom left image is the board as built - I've left off the Pi header and voltage selection jumper for now as I am simply using it as a MCP23017 breakout board, with the optional four pin power, ground & I2C header fitted. Feel free to criticise my soldering and lack of flux cleanup!When I get some long pin 40 way headers, (so I can stack hats) , I'll put one on the board with Address 0x20, and add a piece of matrix board along side it on the otherwise bare extra 14 pins. That will give me space for an I2C level shifter, and a row of four pin headers for hooking up other I2C devices.

author: trevers
author_rank: Contributor
timestamp: April 05, 2018, 06:41:50 pm
content: This has been done before. I followed this and was up in under 10 minutes.https://learn.adafruit.com/raspberry-pi-zero-creation/overviewQuote

author: Ian.M
author_rank: Super Contributor
timestamp: April 05, 2018, 07:07:34 pm
content: That's a good guide, and I've bookmarked it, but its aimed at doing a headless setup for remote access via WiFi, not USB RNDIS tethering.

author: Ian.M
author_rank: Super Contributor
timestamp: August 20, 2021, 08:06:16 am
content: Copied from elsewhere to preserve it, as it turns out I need to make another one:September 4 2020Yesterday I power isolated a $dollar_store$ USB A to micro-B cable so I could use it for my Pi Zero W, when externally powered in USB gadget (device emulation) mode. I slit the outer jacket lengthwise for about an inch and teased out the wires, slipping a matchstick under them to keep them accessible.I knew $dollar_store$ cables were crap, but this made it painfully obvious as there wasn't even a pretence at a foil screen and the two plug shells didn't have any continuity. For a USB 2.0 standard compliant cable it should be under 0.6 ohms, It bears something closely resembling the USB 2.0 logo, but not quite - the side arms of the trident are continuously curved, not angled straights joined by curves. That's not kosher so its definitely a 'China Export' shonky fake.Then it was a matter of needle probing them one at a time through their insulation till I found which one was Vbus by continuity measurement to its A plug contact. The official USB wiring colour code was definitely not present, hence the need to needle probe. I got lucky first time with the pale salmon pink wire. If you needle probe more than one wire take care the needle pricks are spread out so there is no risk of contact.I cut the Vbus wire and eased its insulation back to cut out about a 1/4" length of its core from either end that would vanish back into its insulation so there would have been no risk of a short from a strand end if I'd had to needle probe the other wires. Then it was a matter of massaging the wires back into the jacket with a little soft-setting non-aqueous glue and putting on a whipping with sewing thread to hold the jacket slit closed.It works a treat and I can now use an external PSU for my tethered Pi Zero W, without risking blowing my PC's USB port if I forget and switch off the PC while the Pi is still externally powered.For $dollar_store$ substitute one of our local discount store chains with our unit of currency in their name.

author: Renate
author_rank: Super Contributor
timestamp: August 20, 2021, 06:48:57 pm
content: I've done USB OTG HID on Pi Zero W.I found that BT RFComm was simpler.I use a Zero W as a digital display, but not using X11, simply the Vcore stuff.That's all in /opt/vc/src/hello_pi

author: Ian.M
author_rank: Super Contributor
timestamp: May 26, 2024, 03:48:39 pm
content: More fiddling with tethered Pi Zeros, this time for my local maker spaceA box full of embedded bits and pieces was donated by a member who is no longer able to use them, and amidst the oddments and junk was a poor lonely Pi Zero V1.2, no header, no uSD card, hot-glued to aFE1.1sfour port USB 2.0 hub PCB, hard-wired to testpoints PP1 & PP6 for power and PP22 & PP23 for data. So far, I've debonded the hotglue with IPA, and cleaned off, fitted a 40 pin header, imaged an 8GB uSD card with Raspberry Pi OS (Legacy, Buster) with desktop, and fitted a short micro-USB B cable to the hub board, with its USB plug hacked to ground the ID pin so it puts the Pi into OTG host mode when using the dwc2 module. If the Pi is using the default dwc_OTG module, which locks it into OTG host mode, the ID pin doesn't need to be grounded, which is how the hotglued abomination managed to work originally.I've configured the Pi for RNDIS tethering, and setup my Win10 PC for a tethered Pi. SSH access via Putty is working.ToDo:Figure out the correct incantations for VNC access - complicated by the Pi booting to CLI, not desktopSetup the hackspace's OSX MAC for a tethered PiDocument the above properly3D print or laser cut cases for the Pi Zero and USB HubOrganise as a Pi 'kit in a box'