[{"element_type":"image_url","content":"https://github.com/cadet702/cadet702.github.io/assets/32227645/ea47f33f-0509-47fb-b939-bc03751dcc1a","metadata":{"alt":"five","caption":""}},{"element_type":"text","content":"\n        \u003ch1\u003eInspiration\u003c/h1\u003e\n\u003cp\u003eThis project was born from two desires. One, see if our dog could be taught to use buttons without spending piles of money. Two, to make use of an ancient Raspberry Pi.\u003c/p\u003e\n\u003cp\u003eLots of people have done a project like this, and it isn’t necessary to use a Raspberry Pi. That just happened to be the only unused piece of electronics I had on hand with audio output. But, I will say that I definitely recommend this approach for a couple reasons. Firstly, it’s very easy to get running in Python with \u003ca href=\"https://learn.adafruit.com/circuitpython-on-raspberrypi-linux/installing-circuitpython-on-raspberry-pi\"\u003eAdafruit’s Blinka library\u003c/a\u003e. Second, it leaves lots of room for growth (both in number of buttons and features like button presses sending digital messages).\u003cbr\u003e\u003cbr\u003eBe sure to read all the way to the bottom for a cute puppy photo!\u003c/p\u003e\n      ","metadata":{}},{"element_type":"text","content":"\n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n        \u003ch1\u003eMaterials Used\u003c/h1\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cstrong\u003eRaspberry Pi (low cost model A)\u003c/strong\u003e\n\u003cul\u003e\n\u003cli\u003eGifted by a coworker who was going to throw it out\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cstrong\u003e16GB (full size) SD card\u003c/strong\u003e\n\u003cul\u003e\n\u003cli\u003eCame with my 3D printer, but is overkill for that purpose\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cstrong\u003eAudio cable\u003c/strong\u003e\n\u003cul\u003e\n\u003cli\u003eFrom a box of junk computer parts\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cstrong\u003eAudio amplifier\u003c/strong\u003e\n\u003cul\u003e\n\u003cli\u003eIncluded in a box of junk that got shipped to me\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cstrong\u003eSpeakers\u003c/strong\u003e\n\u003cul\u003e\n\u003cli\u003eFrom an old CRT TV\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cstrong\u003eJumper wires\u003c/strong\u003e\n\u003cul\u003e\n\u003cli\u003eReused from multiple projects\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003ca href=\"https://github.com/cadet702/cadet702.github.io/assets/32227645/aed17f2d-df17-4ad7-ae7e-a9a04e2e11c3\"\u003e\u003cstrong\u003eKeyboard breakout\u003c/strong\u003e\u003c/a\u003e\n\u003cul\u003e\n\u003cli\u003eHand made from salvaged diodes, jumper headers, perf-board, \u003ca href=\"https://github.com/cadet702/cadet702.github.io/assets/32227645/0e41668e-3a69-42b7-ba28-6af87347692c\"\u003ewires, and solder\u003c/a\u003e.\u0026nbsp; Let's call it 50% recycled.\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cstrong\u003e3D printed buttons (and some hotglue)\u003c/strong\u003e\n\u003cul\u003e\n\u003cli\u003eTechnically new, but I don't count 3D prints if they displace buying other plastic\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cstrong\u003eElectronic buttons inside the prints (also a boot button shutdown switch)\u003c/strong\u003e\n\u003cul\u003e\n\u003cli\u003eAll salvaged from ewaste or otherwise discarded\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cstrong\u003eWooden mounting board\u003c/strong\u003e\n\u003cul\u003e\n\u003cli\u003eHad to buy it from a hobby store\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e\u003cstrong\u003eSalvage percentage ~83%!\u0026nbsp; Hard to give an exact number... do you measure by count?\u0026nbsp; By volume?\u0026nbsp; By mass?\u0026nbsp; By value?\u0026nbsp; Do you count new tools you had to buy?\u0026nbsp; Whatever, I'm going to call it 83%.\u003c/strong\u003e\u003c/p\u003e\n      \n\n\n\n\n\n\n\n\n\n\n\n\n\n","metadata":{}},{"element_type":"text","content":"\n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n        \u003ch1\u003e3D Files\u003c/h1\u003e\n\u003cp\u003eRather than reinvent the wheel, I found a \u003ca href=\"https://www.printables.com/en/model/337637-dog-button\"\u003eclever 3D printable button\u003c/a\u003e that only needs at tiny electronic button added at the bottom.\u0026nbsp; I did have to modify the design slightly to add a lip to prevent it falling through the board and add an extra ring inside the base plate to prevent the button from jamming when pressed at an angle.\u0026nbsp; I also made a tiny cylinder to glue onto the button plunger to extend the length if needed.\u0026nbsp; The links to my modified versions are below.\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://www.tinkercad.com/things/aZKm9GllMm0-modified-base?sharecode=hOJRwQdnIUB88RDpqc4PDddWlf6xUr6J8ZB6SfGE3aE\"\u003eButton Base\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://www.tinkercad.com/things/kdht1EzSxxg-button-shim-spring?sharecode=jE5-2YcauABVu66VQ4ks0aRH0FRXuZn2fgHPTA0VsMU\"\u003eCylinder Shim\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://www.tinkercad.com/things/6oxHtgFRSQ3-modified-lock-ring?sharecode=9Yg5l9eCSyFK97Tum16cnf9nxZqSUMWN7bfPKD3Okl0\"\u003eLock Ring With Lip\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://www.tinkercad.com/things/0Vb2FkFXOG9-button-import?sharecode=GiYnVVgcQhuaf9mgJOmiKlSeAUrdV3HO-4YRXFbUn0c\"\u003eButton Top\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://www.tinkercad.com/things/dfdYYs44s31-button-springs?sharecode=CYcnKxhpHh2Kfe0pdWIekePdD8JueeZvUUIrxdHvuhg\"\u003eRing Spring(s)\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n      \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n","metadata":{}},{"element_type":"image_url","content":"","metadata":{"alt":"","caption":""}},{"element_type":"image_url","content":"https://github.com/cadet702/cadet702.github.io/assets/32227645/01d0edee-6df5-4ad3-8965-1b7d1930c095","metadata":{"alt":"Dogs","caption":"Fully assembled, the buttons look like this."}},{"element_type":"image_url","content":"https://github.com/cadet702/cadet702.github.io/assets/32227645/e26d39f8-2b69-44dd-b0c8-f054c2e62fb6","metadata":{"alt":"Oh","caption":"Labeling the buttons with stickers or a label maker is helpful for the humans"}},{"element_type":"text","content":"\n        \u003ch1\u003eSetup Challenges\u003c/h1\u003e\n\u003cp\u003eAncient Raspberry Pi's are great for this type of project because they're relatively low power (only about 0.5A @ 5V), but they do have some development challenges.\u003c/p\u003e\n\u003ch2\u003eChicken and egg\u003c/h2\u003e\n\u003cp\u003eThe earliest Pis didn't have a wi-fi chip built in, you had to plug in an ethernet cable or USB wi-fi adapter.\u0026nbsp; At some point, they also released a cost-reduced version of this Pi with no ethernet adapter and only one USB port instead of two.\u0026nbsp; This makes setup\u0026nbsp;\u003cem\u003every\u003c/em\u003e challenging.\u0026nbsp; If you want to update the OS and install packages (like PIP), you'll need a USB wi-fi adapter plugged in\u0026nbsp;\u003cem\u003eand\u003c/em\u003e a USB keyboard from which to type the commands.\u0026nbsp; Here are a few reasonable options I found while dealing with these devices:\u003c/p\u003e\n\u003col\u003e\n\u003cli\u003e(beginner) Just get a USB splitter.\u0026nbsp; But make sure it's a\u0026nbsp;\u003cem\u003epowered\u003c/em\u003e USB splitter because the Pi can only supply enough juice to power one device (and wi-fi adapters tend to be power hungry).\u003c/li\u003e\n\u003cli\u003e(intermediate) Use and FTDI adapter to connect to the UART pins and connect over serial to type your commands.\u0026nbsp; This leaves the one USB port available for that wi-fi adapter.\u003c/li\u003e\n\u003cli\u003e(intermediate) If you happen to have a wi-fi adapter that works with Raspbian out-of-the-box, you could SSH into the pi from another computer and type your commands that way.\u003c/li\u003e\n\u003cli\u003e(advanced) Use the desktop version of 32-bit Buster to ensure the PPP package is available.\u0026nbsp; Use the UART pins to connect over serial, then use PPP to share your internet connection over serial.\u0026nbsp; Once you've successfully updated your packages and transferred your files, clean up as much of the desktop bloat as possible.\u0026nbsp; I strongly recommend avoiding this process if at all possible.\u0026nbsp; The only reason to consider it is if you can't find a compatible wi-fi adapter or need to modify things to get your USB wi-fi adapter working with Raspbian.\u0026nbsp; I never actually managed to get this process fully working, so if you go this route, good luck!\u003c/li\u003e\n\u003c/ol\u003e\n      ","metadata":{}},{"element_type":"text","content":"\n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n        \u003ch2\u003eBeautiful chaos\u003c/h2\u003e\n\u003cp\u003eI chose to keep things accessible from the underside of the board.\u0026nbsp; From this angle, I can point out some of the more interesting/useful features.\u003c/p\u003e\n\u003cp\u003eThe teal thing connected via USB is a wi-fi dongle.\u003c/p\u003e\n\u003cp\u003eThe small perf-board with a bunch of wires going to it is the common ground for the buttons (only needed in direct wiring).\u003c/p\u003e\n\u003cp\u003ePower and audio cables are routed out a hole in the side for convenience.\u003c/p\u003e\n\u003cp\u003eThe \"shutdown\" button is the white button at the edge of the board.\u0026nbsp; The red button forces a reboot (even it it's already on).\u0026nbsp; The shutdown button is handled by the same software that detects other button presses, but the reboot is done with hardware (\u003ca href=\"https://raspi.tv/2012/making-a-reset-switch-for-your-rev-2-raspberry-pi\"\u003esee this guide\u003c/a\u003e).\u0026nbsp; That makes the reboot button generally unsafe, but I added it because I got tired of having to disconnect the whole device from power after a shutdown and just wanted to be able to press a button to turn it back on.\u003c/p\u003e\n      \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n","metadata":{}},{"element_type":"image_url","content":"https://github.com/cadet702/cadet702.github.io/assets/32227645/e86dfaae-94d9-427d-931b-6795598e4085","metadata":{"alt":"Pi,","caption":"Pi, wi-fi dongle, and shutdown \u0026amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp; reboot buttons hidden on the underside of the board"}},{"element_type":"text","content":"\n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n        \u003ch2\u003eLove (or hate) the command line\u003c/h2\u003e\n\u003cp\u003eEither way, it's what you'll be using.\u0026nbsp; These early Pis are powerful enough to process audio and connect to wi-fi, but you'll be squandering their finite capabilities if you ask them to also support a full desktop environment.\u0026nbsp; But that's ok, you only really need to do a few things to get this running:\u003c/p\u003e\n\u003col\u003e\n\u003cli\u003eUse the 32-bit Bullseye Lite OS image\u003c/li\u003e\n\u003cli\u003eSolve your chicken and egg problem so you can update packages\u003c/li\u003e\n\u003cli\u003eTransfer your files.\u0026nbsp; Either wirelessly with something like PSFTP or with a USB flash drive (but you may have to manually mount it).\u003c/li\u003e\n\u003cli\u003eEdit\u0026nbsp;\u003ccode\u003e/etc/rc.local\u003c/code\u003e so your python script starts on bootup.\u003c/li\u003e\n\u003c/ol\u003e\n      \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n","metadata":{}},{"element_type":"text","content":"\n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n        \u003ch1\u003eHow Many Buttons?\u003c/h1\u003e\n\u003cp\u003eThere's a number of different ways to support buttons.\u0026nbsp; The simplest one is a direct wiring of buttons to pins.\u0026nbsp; This makes the code very simple (see Version 1 below), but limits you to about 13 buttons if you avoid using the I2C and UART pins.\u0026nbsp; You'll also need to tie the grounds together since there aren't enough ground pins for that many buttons.\u003c/p\u003e\n\u003cp\u003eIf you need more, but don't want to roll your own input monitoring and debounce drivers, the CircuitPython keyboard library will let you support up to 6 x 7 = 42 buttons. \u0026nbsp;I'm currently working on the code for this, so I'll add a \u0026nbsp;version 2 code section once it's working and tested.\u003c/p\u003e\n      \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n","metadata":{}},{"element_type":"guide","content":"https://learn.adafruit.com/key-pad-matrix-scanning-in-circuitpython/keymatrix","metadata":{"guide_id":"3367","page_id":"22583"}},{"element_type":"text","content":"\n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n        \u003ch2\u003eMore Buttons?\u003c/h2\u003e\n\u003cp\u003eWhy might you need more than 42 buttons?\u0026nbsp; Easy, if your dog learns words at the rate of 1 a month, your puppy will need more buttons after only 3.5 years!\u0026nbsp; At the moment, the available libraries aren't really designed to support this many buttons from only 13 pins, but if you don't mind writing your own drivers, here are some advanced options to support a lifetime's worth of buttons:\u003c/p\u003e\n\u003col\u003e\n\u003cli\u003eUse \u003ca href=\"https://learn.adafruit.com/key-pad-matrix-scanning-in-circuitpython/shiftregisterkeys\"\u003ean army of shift registers\u003c/a\u003e\u0026nbsp;to extend the number of GPIO.\u0026nbsp; The good news is you can still use the keyboard library.\u0026nbsp; The bad news is you'll need a shift register for every 8 buttons.\u003c/li\u003e\n\u003cli\u003e\n\u003ca href=\"https://en.wikipedia.org/wiki/Charlieplexing\"\u003eCharlieplex\u003c/a\u003e the inputs.\u0026nbsp; This technique lets you support N * (N - 1) buttons from N pins, so in my case, that's 13 * 12 = 156.\u0026nbsp; That's a lot of buttons!\u0026nbsp; But in addition to needing custom drivers, it requires a small mountain of diodes and a complex wiring arrangement.\u003c/li\u003e\n\u003cli\u003eUse SPI or \u003ca href=\"https://www.adafruit.com/product/4132\"\u003eI2C GPIO expanders\u003c/a\u003e.\u0026nbsp; Just be sure to get one that can handle the matrix keyboard, queuing, and debounce stuff for you (see the guide below), otherwise you'll have to develop that yourself.\u0026nbsp; The \u003ca href=\"https://www.adafruit.com/product/4918\"\u003eTCA8418 is a good choice\u003c/a\u003e\u003cspan\u003e, but since it can only have one address you'll need to use two independent I2C buses i\u003c/span\u003ef you need more than 80 buttons.\u003c/li\u003e\n\u003cli\u003eUse another Pi or another microcontroller.\u0026nbsp; If you only need 2x your maximum number of buttons, why not just use two identical units running very similar programs?\u0026nbsp; This is a simple solution, but it makes combining the audio output more complicated if you want to route both outputs to a single set of speakers.\u0026nbsp; Just wiring the outputs together is likely to create a ground loop and generate noise on your speakers unless you have a special connector that is designed to combine audio signals.\u003c/li\u003e\n\u003c/ol\u003e\n      \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n","metadata":{}},{"element_type":"guide","content":"https://learn.adafruit.com/adafruit-tca8418-keypad-matrix-and-gpio-expander-breakout/python-circuitpython","metadata":{"guide_id":"3659","page_id":"24925"}},{"element_type":"text","content":"\n        \u003ch1\u003eCode\u003c/h1\u003e\n\u003ch2\u003eVersion 1 (direct wiring)\u003c/h2\u003e\n      ","metadata":{}},{"element_type":"code","content":"#! /usr/bin/python\n\nimport atexit, pickle, socket, time, subprocess\nimport os, sys, digitalio, busio, pwmio, adafruit_ssd1306, board ## PG added\nfrom board import SCL, SDA\nimport datetime as dt ## PG added\nfrom PIL                   import Image, ImageDraw, ImageFont ## PG added\nfrom adafruit_debouncer    import Debouncer ## PG added\nfrom pygame                import mixer\n\n## Load the sounds:\nmixer.init()\nsound_applause = mixer.Sound('/home/pi/pianobar/wav_files/applause-1.wav')\nsound_play     = mixer.Sound('/home/pi/pianobar/wav_files/play.wav')\nsound_potty    = mixer.Sound('/home/pi/pianobar/wav_files/potty.wav')\nsound_water    = mixer.Sound('/home/pi/pianobar/wav_files/water.wav')\nsound_walk     = mixer.Sound('/home/pi/pianobar/wav_files/walk.wav')\nsound_later    = mixer.Sound('/home/pi/pianobar/wav_files/later.wav')\nsound_anabelle = mixer.Sound('/home/pi/pianobar/wav_files/anabelle.wav')\nsound_outside  = mixer.Sound('/home/pi/pianobar/wav_files/outside.wav')\nsound_hmmm     = mixer.Sound('/home/pi/pianobar/wav_files/hmmm.wav')\n\nHOLD_TIME    = 1.0 # Time (seconds) to hold select button for shut down\n\ndef make_pin_reader(pin):\n    io = digitalio.DigitalInOut(pin)\n    io.direction = digitalio.Direction.INPUT\n    io.pull = digitalio.Pull.UP\n    return lambda: io.value\n\n## define debounced buttons\nD4_TBD1      = Debouncer(make_pin_reader(board.D4),  interval=0.02)\nD7_shutdown  = Debouncer(make_pin_reader(board.D7),  interval=0.02) #CS1\nD8_TBD2      = Debouncer(make_pin_reader(board.D8),  interval=0.02) #CS0\nD9_TBD3      = Debouncer(make_pin_reader(board.D9),  interval=0.02) #MISO\nD10_applause = Debouncer(make_pin_reader(board.D10), interval=0.02) #MOSI\nD11_play     = Debouncer(make_pin_reader(board.D11), interval=0.02) #SCLK\nD17_potty    = Debouncer(make_pin_reader(board.D17), interval=0.02)\nD18_water    = Debouncer(make_pin_reader(board.D18), interval=0.02)\nD22_walk     = Debouncer(make_pin_reader(board.D22), interval=0.02)\nD23_later    = Debouncer(make_pin_reader(board.D23), interval=0.02)\nD24_anabelle = Debouncer(make_pin_reader(board.D24), interval=0.02)\nD25_outside  = Debouncer(make_pin_reader(board.D25), interval=0.02)\nD27_hmmm     = Debouncer(make_pin_reader(board.D27), interval=0.02)\n\nt2 = 0\ncontinue_looping = True\nwhile continue_looping:\n    D4_TBD1.update()\n    D7_shutdown.update()\n    D8_TBD2.update()\n    D9_TBD3.update()\n    D10_applause.update()\n    D11_play.update()\n    D17_potty.update()\n    D18_water.update()\n    D22_walk.update()\n    D23_later.update()\n    D24_anabelle.update()\n    D25_outside.update()\n    D27_hmmm.update()\n\n    if D4_TBD1.fell:      t2 = time.time()\n#    if D7_shutdown.fell: # Handled later\n    if D8_TBD2.fell:      t2 = time.time()\n    if D9_TBD3.fell:      t2 = time.time()\n    if D10_applause.fell: sound_applause.play()\n    if D11_play.fell:     sound_play.play()\n    if D17_potty.fell:    sound_potty.play()\n    if D18_water.fell:    sound_water.play()\n    if D22_walk.fell:     sound_walk.play()\n    if D23_later.fell:    sound_later.play()\n    if D24_anabelle.fell: sound_anabelle.play()\n    if D25_outside.fell:  sound_outside.play()\n    if D27_hmmm.fell:     sound_hmmm.play()\n\n    if D7_shutdown.fell:\n        t = time.time()\n        while not D7_shutdown.value:\n            D7_shutdown.update()\n            if (time.time() - t) \u003e= HOLD_TIME:\n                t2 = time.time()\n                continue_looping = False\n                break # needed in case button isn't released\n\n    if not continue_looping:\n        break\n\n\ntime.sleep(1)\nos.system('sudo shutdown now -h')\nexit(0)","metadata":{"language":"python","linenums":false}},{"element_type":"text","content":"\n  \n        \u003ch2\u003eVersion 2 (matrix keyboard)\u003c/h2\u003e\n\u003cp\u003eThis is the matrix keyboard code.\u0026nbsp; While all recorded sounds are defined, only the currently used buttons are checked in the loop, but this can be extended as our doggy learns more words.\u0026nbsp; I initially included some experimental code for publishing button presses to \u003ca href=\"https://io.adafruit.com/\"\u003eAdafruitIO\u003c/a\u003e, but I've decided that that enhancement is worth of \u003ca href=\"https://adafruit-playground.com/u/cadet702/pages/stuff-my-dog-said-via-adafruitio\"\u003ea separate blog post\u003c/a\u003e.\u003c/p\u003e\n      \n","metadata":{}},{"element_type":"code","content":"#! /usr/bin/python\n\nimport atexit, pickle, socket, time, subprocess\nimport os, sys, digitalio, busio, adafruit_ssd1306, board\nimport keypad\nfrom board import SCL, SDA\nfrom pygame                import mixer\n\n## Load the sounds:\nmixer.init()\nsound_applause = mixer.Sound('/home/pi/pianobar/wav_files/applause-1.wav')\n\nsound_play       = mixer.Sound('/home/pi/pianobar/wav_files/play.wav')\nsound_potty      = mixer.Sound('/home/pi/pianobar/wav_files/potty.wav')\nsound_water      = mixer.Sound('/home/pi/pianobar/wav_files/water.wav')\nsound_walk       = mixer.Sound('/home/pi/pianobar/wav_files/walk.wav')\nsound_later      = mixer.Sound('/home/pi/pianobar/wav_files/later.wav')\nsound_anabelle   = mixer.Sound('/home/pi/pianobar/wav_files/anabelle.wav')\nsound_outside    = mixer.Sound('/home/pi/pianobar/wav_files/outside.wav')\nsound_hmmm       = mixer.Sound('/home/pi/pianobar/wav_files/hmmm.wav')\nsound_daddy      = mixer.Sound('/home/pi/pianobar/wav_files/daddy.wav')\nsound_mommy      = mixer.Sound('/home/pi/pianobar/wav_files/mommy.wav')\n\nsound_all_done   = mixer.Sound('/home/pi/pianobar/wav_files/all-done-happy-v2.wav')\nsound_ball       = mixer.Sound('/home/pi/pianobar/wav_files/ball.wav')\nsound_bed_time   = mixer.Sound('/home/pi/pianobar/wav_files/bed-time.wav')\nsound_cuddles    = mixer.Sound('/home/pi/pianobar/wav_files/cuddles.wav')\nsound_downstairs = mixer.Sound('/home/pi/pianobar/wav_files/downstairs.wav')\nsound_hard       = mixer.Sound('/home/pi/pianobar/wav_files/hard-best-v4.wav')\nsound_lazer      = mixer.Sound('/home/pi/pianobar/wav_files/lazer.wav')\nsound_lila       = mixer.Sound('/home/pi/pianobar/wav_files/lila.wav')\nsound_love_you   = mixer.Sound('/home/pi/pianobar/wav_files/love-you.wav')\nsound_nap_time   = mixer.Sound('/home/pi/pianobar/wav_files/nap-time.wav')\nsound_noise      = mixer.Sound('/home/pi/pianobar/wav_files/noise.wav')\nsound_pets       = mixer.Sound('/home/pi/pianobar/wav_files/pets.wav')\nsound_soft       = mixer.Sound('/home/pi/pianobar/wav_files/soft.wav')\nsound_thea       = mixer.Sound('/home/pi/pianobar/wav_files/thea.wav')\nsound_tug        = mixer.Sound('/home/pi/pianobar/wav_files/tug.wav')\nsound_upstairs   = mixer.Sound('/home/pi/pianobar/wav_files/upstairs.wav')\nsound_want       = mixer.Sound('/home/pi/pianobar/wav_files/want.wav')\nsound_yard       = mixer.Sound('/home/pi/pianobar/wav_files/yard.wav')\n\nkm = keypad.KeyMatrix(\n    row_pins=(board.D4, board.D7, board.D8, board.D11, board.D9, board.D10),\n    column_pins=(board.D17, board.D18, board.D27, board.D22, board.D23, board.D24, board.D25),\n    columns_to_anodes=True,\n)\n\nwhile True:\n    event = km.events.get()\n    if event:\n        print(event)\n        if event.pressed == True and event.key_number == 26: sound_later.play()\n        if event.pressed == True and event.key_number == 25: sound_water.play()\n        if event.pressed == True and event.key_number == 27: sound_walk.play()\n        if event.pressed == True and event.key_number == 24: sound_potty.play()\n        if event.pressed == True and event.key_number == 23: sound_outside.play()\n        if event.pressed == True and event.key_number == 22: sound_play.play()\n        if event.pressed == True and event.key_number == 21: sound_hmmm.play()\n        if event.pressed == True and event.key_number ==  5: sound_daddy.play()\n        if event.pressed == True and event.key_number ==  1: sound_mommy.play()\n\n        if event.pressed == True and event.key_number ==  0:\n            break\n\nos.system('sudo shutdown now -h')\nexit(0)","metadata":{"language":"python","linenums":false}},{"element_type":"markdown","content":"\u003ch1\u003eHow to Train Your \u003cdel\u003eDragon\u003c/del\u003e Doggy\u003c/h1\u003e\n","metadata":{"markdown":"# How to Train Your ~~Dragon~~ Doggy"}},{"element_type":"text","content":"\n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n        \u003cp\u003eThere's a lot of advice online that says to start with \"treat\".\u0026nbsp; I recommend ignoring that advice.\u0026nbsp; For one, that only teaches them to push a button, and you can do that without making the button \"treat\".\u0026nbsp; Secondly, if your dog is even slightly food motivated, it'll be the only button they want to press.\u0026nbsp; And good luck taking that button away later.\u003c/p\u003e\n\u003cp\u003eStart with \"potty\" or whatever word you use for that.\u0026nbsp; It will likely be the single most useful button they ever learn.\u0026nbsp; Reward your dog for showing any interest in the button board when it's introduced.\u0026nbsp; Reward your dog for interacting with the button.\u0026nbsp; When ever you take the dog outside to potty, first go over and press the button, then take your dog out to potty.\u003c/p\u003e\n\u003cp\u003eThe hardest part is helping them understand that\u0026nbsp;\u003cem\u003ethey\u003c/em\u003e can press the button.\u0026nbsp; They'll learn pretty quickly that you pressing the button is part of the going potty ritual, but helping them understand that\u0026nbsp;\u003cem\u003ethey\u003c/em\u003e can make that request via the button is what takes time.\u003c/p\u003e\n\u003cp\u003eOnce they've mastered \"potty\", you can start introducing other words, one at a time.\u0026nbsp; Dogs don't have the same color perception that we do and generally learn the buttons by their relative position, so you're likely to confuse them if you rearrange the buttons.\u003c/p\u003e\n      \n\n\n\n\n\n\n\n\n\n\n","metadata":{}},{"element_type":"image_url","content":"https://github.com/cadet702/cadet702.github.io/assets/32227645/dce117d8-56ac-4457-a13f-9796844cafcb","metadata":{"alt":"Why","caption":""}}]