{"id":398,"date":"2018-12-17T23:19:40","date_gmt":"2018-12-17T23:19:40","guid":{"rendered":"https:\/\/elephantandchicken.co.uk\/stuffandnonsense\/?p=398"},"modified":"2018-12-17T23:31:18","modified_gmt":"2018-12-17T23:31:18","slug":"driving-ws2812b-leds-with-a-raspberry-pi","status":"publish","type":"post","link":"https:\/\/elephantandchicken.co.uk\/stuffandnonsense\/?p=398","title":{"rendered":"Driving WS2812B LEDs with a Raspberry Pi"},"content":{"rendered":"<p>Writing LED sequences can be quite a faff when you&#8217;re making your own programs and hardware. I decided that a handy way of visualising the patterns would be&#8230; to visualise them, as an image. To do this, I&#8217;ve written a simple program that takes a bitmap image and outputs the colours of each pixel in each row, to the corresponding LED. The image is the same width as the target number of pixels, and each row represents a frame.<\/p>\n<p>This allows me to do my LED sequencing using software I&#8217;m already familiar with, such as Photoshop or GIMP.<\/p>\n<div id=\"attachment_399\" style=\"width: 90px\" class=\"wp-caption aligncenter\"><a href=\"https:\/\/elephantandchicken.co.uk\/stuffandnonsense\/wp-content\/uploads\/2018\/12\/CylonEyes.png\"><img aria-describedby=\"caption-attachment-399\" loading=\"lazy\" class=\"wp-image-399 size-full\" src=\"https:\/\/elephantandchicken.co.uk\/stuffandnonsense\/wp-content\/uploads\/2018\/12\/CylonEyes.png\" alt=\"Cylon Eyes\" width=\"80\" height=\"140\" \/><\/a><p id=\"caption-attachment-399\" class=\"wp-caption-text\">Cylon Eyes<\/p><\/div>\n<p>So far, I&#8217;ve had versions of the program (re-written for required variations in available libraries) running on the Orange Pi (Armbian), ESP8266 (Arduino IDE) and the Raspberry Pi (twice, because I lost the original version). This post covers the latter, using the current libraries discussed on the Adafruit website, which unfortunately seem to only work with Python 3.<\/p>\n<h6>Required Equipment &amp; Setup<\/h6>\n<p>For this tutorial, you will require the following :<\/p>\n<ul>\n<li>A Raspberry Pi, cables and an SD card<\/li>\n<li>A string of WS2812B LEDs &#8211; 8 is a good number<\/li>\n<li>Appropriate wires to connect the LEDs to the Raspberry Pi GPIO header<\/li>\n<\/ul>\n<p>I&#8217;ve used <a href=\"https:\/\/www.banggood.com\/CJMCU-8-Bit-WS2812-5050-RGB-LED-Driver-Development-Board-p-958214.html\">the linked LEDs as they are convenient for testing<\/a>. You will need to solder wires, or a header to these &#8211; I usually lay a standard male header (4 pins) on the pads and solder it down as it is handy for prototyping. The male header lets me use female-&gt;female dupont wires to connect to a Raspberry Pi. Also note that some variations have the red and green wired backwards &#8211; this can be easily be fixed in software (I have included a boolean near the start of the code in pictureLED.py to enable the switch).<\/p>\n<p>The LEDs should be wired into the Raspberry Pi while it is powered down to reduce the chance of fatal mistakes (always rewire with a computer powered down as they are <em>very<\/em> sensitive to electrical shocks and the GPIO pins are wired directly into the inner gubbins of the main chip). Wiring is as follows, where the red wire goes to +5v, the blue wire to data and the black wire to ground (there are two on the suggested LED part which is useful when using separate power supplies for the Raspberry Pi and the LEDs).<\/p>\n<div id=\"attachment_401\" style=\"width: 919px\" class=\"wp-caption aligncenter\"><a href=\"https:\/\/elephantandchicken.co.uk\/stuffandnonsense\/wp-content\/uploads\/2018\/12\/RasPiRGBWiring.png\"><img aria-describedby=\"caption-attachment-401\" loading=\"lazy\" class=\"size-full wp-image-401\" src=\"https:\/\/elephantandchicken.co.uk\/stuffandnonsense\/wp-content\/uploads\/2018\/12\/RasPiRGBWiring.png\" alt=\"Raspberry Pi LED Wiring\" width=\"909\" height=\"684\" srcset=\"https:\/\/elephantandchicken.co.uk\/stuffandnonsense\/wp-content\/uploads\/2018\/12\/RasPiRGBWiring.png 909w, https:\/\/elephantandchicken.co.uk\/stuffandnonsense\/wp-content\/uploads\/2018\/12\/RasPiRGBWiring-300x226.png 300w\" sizes=\"(max-width: 909px) 100vw, 909px\" \/><\/a><p id=\"caption-attachment-401\" class=\"wp-caption-text\">Raspberry Pi LED Wiring<\/p><\/div>\n<p>The WS2812B LEDs are only borderline able to be driven from 3.3v to the data pin (the Raspberry Pi does this). While this is true, with short wires I have never had an issue. I will detail how to use a MOSFET to increase the data signal voltage to 5v later.<\/p>\n<p>I will assume you have a clean install of Raspbian on the SD card in the Raspberry Pi. Before doing anything else, ensure you run the following command in a terminal :<\/p>\n<blockquote><p>sudo apt-get update<\/p><\/blockquote>\n<p>This updates the database of software on the Raspberry Pi and ensures that you&#8217;re requesting the latest versions of programs.<\/p>\n<p>Next run the following commands in a terminal :<\/p>\n<blockquote><p>sudo pip3 install rpi_ws281x<\/p>\n<p>sudo pip3 install adafruit-circuitpython-neopixel<\/p><\/blockquote>\n<p>The first time I ran these commands, I had an error for an unknown reason. I ran them again and everything installed properly.<\/p>\n<h6>First Test<\/h6>\n<p>To make sure everything is working, enter the following program into your favourite text editor on your Raspberry Pi and save it as test.py in a new folder (creating a new folder in the current directory : mkdir &lt;foldername&gt;, switch into the new folder : cd &lt;foldername&gt;, editor suggestion : nano test.py).<\/p>\n<pre class=\"lang:python decode:true\" title=\"First Test\">#!\/usr\/bin\/env python3\r\n# The line above tells the Raspberry Pi that we want to run this\r\n#   script in Python 3 - so we don't have to tell it later\r\n\r\nimport board\r\nimport neopixel\r\nfrom time import sleep\r\n\r\n# An example program that cycles through Red, Green Blue and then stops\r\n\r\nLEDcount = 8\r\n\r\npixels = neopixel.NeoPixel(board.D18, LEDcount)\r\n\r\n#red\r\npixels.fill((100,0,0))\r\nsleep(1)\r\n#green\r\npixels.fill((0,100,0))\r\nsleep(1)\r\n#blue\r\npixels.fill((0,0,100))\r\nsleep(1)\r\n\r\n# and off\r\npixels.fill((0,0,0))\r\n<\/pre>\n<p>If you&#8217;re powering the LEDs from the Raspberry Pi, do not turn on too many. 8 is likely to already be too many as they use up to 60mA each (480mA for 8!). To limit power in these examples, I&#8217;m not using full brightness (full brightness would be 255 in the first test program), limiting the number of lit LEDs or am only using single colours at a time. For white light and full brightness on all LEDs &#8211; use an external power supply if you have more than one or two LEDs! Thanks to <a href=\"https:\/\/www.pjrc.com\/how-much-current-do-ws2812-neopixel-leds-really-use\/\">PJRC for actually doing some measurements<\/a>.<\/p>\n<p>Once entered and saved, from a terminal in the saved file&#8217;s directory, enter the following command to give the file permission to execute as a script :<\/p>\n<blockquote><p>chmod +x test.py<\/p><\/blockquote>\n<p>&#8220;chmod&#8221; is the permissions modification command and I think of &#8220;+x&#8221; as meaning &#8220;plus executable&#8221;.<\/p>\n<p>We&#8217;re ready to run our test &#8211; with everything connected, run the following command in the terminal :<\/p>\n<blockquote><p>sudo .\/test.py<\/p><\/blockquote>\n<p>If everything goes to play, you should see the connected LEDs cycle through red, green and then blue before turning off. If you see any errors, google is your friend. Also check that you ran the command while in the correct directory, and have permission to use the sudo command.<\/p>\n<h6>Make a &#8220;Clear&#8221; Script<\/h6>\n<p>A useful script to make at this stage is a &#8220;clear&#8221; script. This means if you interrupt another script, or create a script that leaves LEDs on and you want to get rid of them, you can run this script to tidy them up.<\/p>\n<pre class=\"lang:python decode:true\" title=\"clear.py\">#!\/usr\/bin\/env python3\r\nimport board\r\nimport neopixel\r\nimport sys\r\n\r\n# assume a default 200 LEDs\r\nLEDcount = 200\r\n\r\n# handle parameter\r\nif len(sys.argv) == 2:\r\n   # we have been passed a parameter - this should be the number of LEDs\r\n   LEDcount = int(sys.argv[1])\r\n\r\npixels = neopixel.NeoPixel(board.D18, LEDcount)\r\n\r\npixels.fill((0,0,0))<\/pre>\n<p>As before, enter the program, save it with a name (clear.py for example) and then make it executable with chmod. This script can be used in two ways &#8211; if you note the &#8220;handle parameter&#8221; if statement, by using a parameter when running the script you can define how many LEDs you would like to clear. If no parameter is passed, the script assumes you have 200. Note that overestimating is not an issue and so 200 will clear any number up to 200. If you have 201 LEDs, the final LED will remain lit!<\/p>\n<p>To use the script you&#8217;ve just entered, type the following at the command line :<\/p>\n<blockquote><p>sudo .\/clear.py<\/p><\/blockquote>\n<p>This will clear the first 200 LEDs. To clear a specific number of LEDs (for example, the first 4 of 8 LEDs or if you have 450 LEDs) :<\/p>\n<blockquote><p>sudo .\/clear.py 4<\/p>\n<p>sudo .\/clear.py 450<\/p><\/blockquote>\n<h6>Preparing an Image<\/h6>\n<p>Creating the Image we&#8217;ll be using to control the LEDs is fairly trivial if you are familiar with any painting programs. The more basic the painting software, the easier the creation! The only complication is making sure that you save in the correct file format (24bit bitmap &#8220;.bmp&#8221;). Note that I previously tested JPEGs, but found that the compression made black not equal 0,0,0 and so LEDs would be visibly lit when I didn&#8217;t want them to be.<\/p>\n<p>For demonstration, I will use GIMP to create my image, because it is free.<\/p>\n<ol>\n<li>Launch GIMP and create a new image. Make it as wide in pixels as the number of LEDs you have connected (8 for me) and as tall as the number of frames you&#8217;d like (16 for me).\n<p><div id=\"attachment_407\" style=\"width: 392px\" class=\"wp-caption aligncenter\"><a href=\"https:\/\/elephantandchicken.co.uk\/stuffandnonsense\/wp-content\/uploads\/2018\/12\/NewImage.png\"><img aria-describedby=\"caption-attachment-407\" loading=\"lazy\" class=\"size-full wp-image-407\" src=\"https:\/\/elephantandchicken.co.uk\/stuffandnonsense\/wp-content\/uploads\/2018\/12\/NewImage.png\" alt=\"New Image\" width=\"382\" height=\"304\" srcset=\"https:\/\/elephantandchicken.co.uk\/stuffandnonsense\/wp-content\/uploads\/2018\/12\/NewImage.png 382w, https:\/\/elephantandchicken.co.uk\/stuffandnonsense\/wp-content\/uploads\/2018\/12\/NewImage-300x239.png 300w\" sizes=\"(max-width: 382px) 100vw, 382px\" \/><\/a><p id=\"caption-attachment-407\" class=\"wp-caption-text\">New Image<\/p><\/div><\/li>\n<li>Fill the drawing area with black (RGB 0,0,0).<\/li>\n<li>Zoom in lots until you can see individual pixels and start painting. The pencil (individual pixel drawing tool) is probably best for this. In GIMP you need to change the pencil &#8220;brush&#8221; size to 1px.<\/li>\n<li>Draw your picture.<\/li>\n<li>Once done, to save in GIMP, select &#8220;Export As&#8230;&#8221; from the File menu.\n<p><div id=\"attachment_405\" style=\"width: 679px\" class=\"wp-caption aligncenter\"><a href=\"https:\/\/elephantandchicken.co.uk\/stuffandnonsense\/wp-content\/uploads\/2018\/12\/ExportImage01.png\"><img aria-describedby=\"caption-attachment-405\" loading=\"lazy\" class=\"size-full wp-image-405\" src=\"https:\/\/elephantandchicken.co.uk\/stuffandnonsense\/wp-content\/uploads\/2018\/12\/ExportImage01.png\" alt=\"Export Image\" width=\"669\" height=\"525\" srcset=\"https:\/\/elephantandchicken.co.uk\/stuffandnonsense\/wp-content\/uploads\/2018\/12\/ExportImage01.png 669w, https:\/\/elephantandchicken.co.uk\/stuffandnonsense\/wp-content\/uploads\/2018\/12\/ExportImage01-300x235.png 300w\" sizes=\"(max-width: 669px) 100vw, 669px\" \/><\/a><p id=\"caption-attachment-405\" class=\"wp-caption-text\">Export Image<\/p><\/div><\/li>\n<li>Name your file, pick a location, select &#8220;Windows BMP image&#8221; and click Export.\n<p><div id=\"attachment_406\" style=\"width: 291px\" class=\"wp-caption aligncenter\"><a href=\"https:\/\/elephantandchicken.co.uk\/stuffandnonsense\/wp-content\/uploads\/2018\/12\/ExportImage02.png\"><img aria-describedby=\"caption-attachment-406\" loading=\"lazy\" class=\"size-full wp-image-406\" src=\"https:\/\/elephantandchicken.co.uk\/stuffandnonsense\/wp-content\/uploads\/2018\/12\/ExportImage02.png\" alt=\"Export Options\" width=\"281\" height=\"466\" srcset=\"https:\/\/elephantandchicken.co.uk\/stuffandnonsense\/wp-content\/uploads\/2018\/12\/ExportImage02.png 281w, https:\/\/elephantandchicken.co.uk\/stuffandnonsense\/wp-content\/uploads\/2018\/12\/ExportImage02-181x300.png 181w\" sizes=\"(max-width: 281px) 100vw, 281px\" \/><\/a><p id=\"caption-attachment-406\" class=\"wp-caption-text\">Export Options<\/p><\/div><\/li>\n<li>Select &#8220;24 bits&#8221; under &#8220;Advanced Options&#8221; in the Export Image as BMP dialog box which appears.<\/li>\n<\/ol>\n<p>I have created the following example.bmp. Note the red graduated tint in the lower half (only between 0 and 80 out of 255 intensity, which will be significantly more pronounced on the LEDs). I have uploaded the actual file (the following image has been enlarged to make it visible) and it can be <a href=\"http:\/\/elephantandchicken.co.uk\/downloads\/WS2812\/example.bmp\">downloaded from here<\/a> (right click and select &#8220;Save link as&#8230;&#8221;).<\/p>\n<div id=\"attachment_404\" style=\"width: 90px\" class=\"wp-caption aligncenter\"><a href=\"https:\/\/elephantandchicken.co.uk\/stuffandnonsense\/wp-content\/uploads\/2018\/12\/exampleBig.png\"><img aria-describedby=\"caption-attachment-404\" loading=\"lazy\" class=\"wp-image-404 size-full\" src=\"https:\/\/elephantandchicken.co.uk\/stuffandnonsense\/wp-content\/uploads\/2018\/12\/exampleBig.png\" alt=\"Example\" width=\"80\" height=\"160\" \/><\/a><p id=\"caption-attachment-404\" class=\"wp-caption-text\">Example<\/p><\/div>\n<p>If you have drawn your image on a computer other than your Raspberry Pi, you will want to transfer it. There are many ways of doing this, from USB drive, to email. I will be using a built in tool command line tool available on Linux and MacOS called &#8220;scp&#8221;.<\/p>\n<p>In this example, we are assuming that the image file is saved in a folder called &#8220;To Transfer&#8221; in your home folder on your desktop \/ laptop computer (aka &#8220;the source&#8221;), is called &#8220;example.bmp&#8221;, that the network name of your Raspberry Pi (aka &#8220;the destination&#8221;) is still the default &#8220;raspberrypi&#8221;, the username is the default &#8220;pi&#8221; and that you want to move it to a folder in the Raspberry Pi home directory called &#8220;RGBLED&#8221;.<\/p>\n<p><em>If you haven&#8217;t consciously changed the network name from &#8220;raspberrypi&#8221;, it will still be this &#8211; if you have, use the new name instead. You can see the network name in the command prompt on the Raspberry Pi if I remember correctly, it is the bit after the &#8220;@&#8221; symbol).<\/em><\/p>\n<p>To move the file from the source to the destination, enter the following command on the source computer :<\/p>\n<blockquote><p>scp ~\/To\\ Transfer\/example.bmp pi@raspberrypi.local:~\/RGBLED\/<\/p><\/blockquote>\n<p>You will be asked for your Raspberry Pi password (the destination, not the source) and you should almost instantly see the file as 100% sent and the source returns to the standard command prompt. If there is an error, make sure that the source and destination are on the same network, the file paths are correct at both ends, the password is correct and that you haven&#8217;t made any typos. If you still have issues, there are websites available that will take you through the process more carefully if you search for &#8220;transferring files to a Raspberry Pi using scp&#8221;.<\/p>\n<p>In later examples, I will assume that the file &#8220;example.bmp&#8221; is located in the ~\/RGBLED\/ (also known as \/home\/pi\/RGBLED\/) folder on the Raspberry Pi.<\/p>\n<h6>The pictureLED.py Script<\/h6>\n<p>The main python script which converts an image into a sequence of LED based patterns is as follows, or can be<a href=\"http:\/\/elephantandchicken.co.uk\/downloads\/WS2812\/pictureLED.py\"> downloaded directly from here<\/a> (right click and select &#8220;Save link as&#8230;&#8221;). I recommend placing it in the same &#8220;~\/RGBLED\/&#8221; folder on the Raspberry Pi.<\/p>\n<pre class=\"lang:python decode:true\" title=\"pictureLED.py\">#!\/usr\/bin\/env python3\r\n\r\n#******************\r\n#* pictureLED.py - convert bmp image into LED sequence Code\r\n#* https:\/\/elephantandchicken.co.uk\/stuffandnonsense\r\n#* Circuit :\r\n#* Connect LED ground to both the Raspberry Pi ground and the LED power supply's ground\r\n#* Connect LED data to pin D18 (if not boosting with MOSFET)\r\n#* Connect LED +V to the LED power supply 5V\r\n#* Do not mix 5V and 3.3V!\r\n#* If in doubt, details of the circuit and software for controlling from linux\r\n#* are on my website\r\n#*******************\r\n\r\nimport sys\r\nimport board\r\nimport neopixel\r\nfrom PIL import Image\r\n\r\nfrom time import sleep\r\n\r\n# Edit the following line if red and green are backwards\r\nswitchColours = false\r\n\r\ndef fixColour(colour, scale):\r\n    # correct the colour order for my ws2812 LEDs and scale the brightness\r\n    # correct colour by switching [0], [1] and [2]\r\n    theResult = (int(scale*colour[0]\/100),int(scale*colour[1]\/100),int(scale*colour[2]\/100))\r\n    if switchColours:\r\n        theResult = (int(scale*colour[1]\/100),int(scale*colour[0]\/100),int(scale*colour[2]\/100))\r\n    return theResult\r\n\r\nif len(sys.argv) == 1:\r\n    print(\"You've not provided any details! Command format is &lt;required&gt; [option] : sudo pictureLED.py &lt;image.bmp&gt; [fps] [loop? 1\/0] [loopdelay] [brightness percent] [pin]\")\r\n    quit()\r\nif len(sys.argv) &gt; 1:\r\n    # identify image file - use defaults for all other parameters\r\n    imgfile = sys.argv[1]\r\n    fps = 15.0\r\n    maxIntensity = 100\r\n    pin = 18\r\n    loopimg = True\r\n    loopDelay = 0\r\nif len(sys.argv) &gt; 2:\r\n    # set the fps\r\n    fps = float(sys.argv[2])\r\nif len(sys.argv) &gt; 3:\r\n    # loop?\r\n    if sys.argv[3] == \"1\":\r\n        loopimg = True\r\n    else:\r\n        loopimg = False\r\nif len(sys.argv) &gt; 4:\r\n    # loop delay (at the end of each cycle)\r\n    loopDelay = float(sys.argv[4])\r\nif len(sys.argv) &gt; 5:\r\n    # set a maximum LED intensity and scale all values\r\n    maxIntensity = int(sys.argv[5])\r\nif len(sys.argv) &gt; 6:\r\n    # parameter 5 - set pin for neopixel data\r\n    pin = sys.argv[6]\r\nim = Image.open(imgfile)\r\npix = im.load()\r\npixw = im.size[0]\r\npixh = im.size[1]\r\nprint(\"Image size = \",im.size)\r\nPIXEL_NUM = pixw\r\n\r\nif pin==18:\r\n    pinName = board.D18\r\n    # add other options here\r\nelse:\r\n    pinName = board.D18\r\n\r\npixels = neopixel.NeoPixel(pinName, PIXEL_NUM, auto_write=False) # pin, number of LEDs\r\n\r\nstat = True\r\n\r\nwhile(stat):\r\n    for y in range(0, pixh):\r\n        for x in range(0, pixw):\r\n            pixels[x] = fixColor([pix[x,y][1],pix[x,y][0],pix[x,y][2]],maxIntensity)\r\n        pixels.show()\r\n        sleep(1\/(fps))\r\n    sleep(loopDelay)\r\n    stat = loopimg\r\npixels.fill((0,0,0))\r\npixels.show()<\/pre>\n<p class=\"\">The program is not actually that large, with the majority of it being a clumsy decoding of the various parameters sent by the user when they execute the command. For a fixed application, much of this could be removed to produce something like the following (untested) code :<\/p>\n<pre class=\"minimize:true lang:python decode:true\" title=\"fixedPictureLED.py - Click to expand\">#!\/usr\/bin\/env python3\r\n\r\n#******************\r\n#* fixedPictureLED.py - convert bmp image into LED sequence Code\r\n#* https:\/\/elephantandchicken.co.uk\/stuffandnonsense\r\n#* Circuit :\r\n#* Connect LED ground to both the Raspberry Pi ground and the LED power supply's ground\r\n#* Connect LED data to pin D18 (if not boosting with MOSFET)\r\n#* Connect LED +V to the LED power supply 5V\r\n#* Do not mix 5V and 3.3V!\r\n#* If in doubt, details of the circuit and software for controlling from linux\r\n#* are on my website\r\n#*******************\r\n\r\nimport sys\r\nimport board\r\nimport neopixel\r\nfrom PIL import Image\r\n\r\nfrom time import sleep\r\n\r\n#################\r\n# Define the image path here!\r\nimgfile = \"\/path\/to\/the\/image.bmp\"\r\n#################\r\n\r\n# Other parameters :\r\nfps = 15.0\r\nmaxIntensity = 100\r\npin = 18\r\nloopimg = True\r\nloopDelay = 0\r\nswitchColours = false\r\n\r\ndef fixColour(colour, scale):\r\n    # correct the colour order for my ws2812 LEDs and scale the brightness\r\n    # correct colour by switching [0], [1] and [2]\r\n    theResult = (int(scale*colour[0]\/100),int(scale*colour[1]\/100),int(scale*colour[2]\/100)) \r\n    if switchColours:\r\n        theResult = (int(scale*colour[0]\/100),int(scale*colour[1]\/100),int(scale*colour[2]\/100)) \r\n    return theResult\r\n\r\nim = Image.open(imgfile)\r\npix = im.load()\r\npixw = im.size[0]\r\npixh = im.size[1]\r\nprint(\"Image size = \",im.size)\r\nPIXEL_NUM = pixw\r\n\r\nif pin==18:\r\n    pinName = board.D18\r\n    # add other options here\r\nelse:\r\n    pinName = board.D18\r\n\r\npixels = neopixel.NeoPixel(pinName, PIXEL_NUM, auto_write=False) # pin, number of LEDs\r\n\r\nstat = True\r\n\r\nwhile(stat):\r\n    for y in range(0, pixh):\r\n        for x in range(0, pixw):\r\n            pixels[x] = fixColor([pix[x,y][1],pix[x,y][0],pix[x,y][2]],maxIntensity)\r\n        pixels.show()\r\n        sleep(1\/(fps))\r\n    sleep(loopDelay)\r\n    stat = loopimg\r\npixels.fill((0,0,0))\r\npixels.show()<\/pre>\n<p>Note the &#8220;auto_write=False&#8221; parameter passed when generating the &#8220;pixels&#8221; object. This changes the library&#8217;s behaviour so that it only sends updates to the LEDs once the function &#8220;pixels.show()&#8221; is called.<\/p>\n<p>As before, once you have pictureLED.py saved (pictureLED.py specifically as fixedPictureLED.py is just an example application) on the Raspberry Pi, run the chmod command to allow the file to be executed.<\/p>\n<h6>Running the pictureLED.py Script<\/h6>\n<p>To run pictureLED.py, open a terminal with the current directory matching the location of both pictureLED.py and example.bmp. The command format is as follows :<\/p>\n<blockquote><p>sudo .\/pictureLED.py &lt;filename.bmp&gt; [fps] [loop? 1\/0] [loopdelay] [brightness percent] [pin]<\/p><\/blockquote>\n<p>Parameters between &#8220;&lt;&gt;&#8221; are required and parameters between &#8220;[]&#8221; are optional, although all preceding optional parameters are required. These are two example commands :<\/p>\n<blockquote><p>sudo .\/pictureLED.py example.bmp<\/p>\n<p>sudo .\/pictureLED.py example.bmp 2 0 0 50<\/p><\/blockquote>\n<p>The first example uses all default settings (15 fps, loop, zero second loop delay (time before the pattern repeats), 0% brightness reduction and the default pin) on the image &#8220;example.bmp&#8221;. The pattern will repeat indefinitely &#8211; to stop it, press Ctrl-c.<\/p>\n<p>The second example passes a number of parameters, more specifically describing how we want the program to run. In this example, we run at 2 fps, not looping, zero second loop delay, at 50% of full brightness. Note we do not specify the pin &#8211; this is because pin D18 is currently the only available pin in my code.<\/p>\n<h6>Running at Boot<\/h6>\n<p>A simple way to make your LED sequence run when the Raspberry Pi powers on (note, powers on, not when you log in) is to edit the operating system file &#8220;\/etc\/rc.local&#8221;. Absolute care should be taken, as if you make a mistake, the Raspberry Pi will not finish booting. Assuming that the absolute path (from the root level of the disk, not from the Home (aka &#8220;~&#8221;) folder) for pictureLED.py is &#8220;\/home\/pi\/RGBLED\/pictureLED.py&#8221;, enter the following command in a terminal :<\/p>\n<blockquote><p>sudo nano \/etc\/rc.local<\/p><\/blockquote>\n<p>A file will open in the text editor nano. Use the arrow keys to scroll to the bottom of the file. The last line should be &#8220;exit 0&#8221;. <strong>Above<\/strong> <strong>this <\/strong>enter the following new text :<\/p>\n<blockquote><p>\/home\/pi\/RGBLED\/pictureLED.py \/home\/pi\/RGBLED\/example.bmp 2 &amp;<\/p><\/blockquote>\n<p>There are a number of things to note here.<\/p>\n<ul>\n<li>All paths have to be absolute as this means that they are always correct, no matter where the current directory is when the script executes.<\/li>\n<li>&#8220;sudo&#8221; is not needed because the parent script is already executing with root permissions.<\/li>\n<li>As shown it is best <strong>(don&#8217;t not do it<\/strong>) to include a &#8221; &amp;&#8221; (that is a space followed by an ampersand). This tells the computer to run the script as a background process and means that if your script throws and error, or stops to wait for user input, the computer does not hang but keeps booting. It also means that the computer doesn&#8217;t wait for your script to finish before continuing (imagine we used the default &#8220;loop&#8221; option).<\/li>\n<\/ul>\n<h6>External Power Supply<\/h6>\n<p>To drive more LEDs at full brightness, connect the LEDs to an external 5v power supply, remembering to connect the ground between both the LED power supply and the Raspberry Pi (not doing so can damage the Raspberry Pi or LEDs as connecting the grounds holds both devices to the same reference point and avoids the voltages floating between the two supplies, potentially causing high voltages where there shouldn&#8217;t be). The following shows a suggested wiring :<\/p>\n<div id=\"attachment_410\" style=\"width: 821px\" class=\"wp-caption aligncenter\"><a href=\"https:\/\/elephantandchicken.co.uk\/stuffandnonsense\/wp-content\/uploads\/2018\/12\/RasPiRGBExternalWiring.png\"><img aria-describedby=\"caption-attachment-410\" loading=\"lazy\" class=\"size-full wp-image-410\" src=\"https:\/\/elephantandchicken.co.uk\/stuffandnonsense\/wp-content\/uploads\/2018\/12\/RasPiRGBExternalWiring.png\" alt=\"External Power LED Wiring\" width=\"811\" height=\"675\" srcset=\"https:\/\/elephantandchicken.co.uk\/stuffandnonsense\/wp-content\/uploads\/2018\/12\/RasPiRGBExternalWiring.png 811w, https:\/\/elephantandchicken.co.uk\/stuffandnonsense\/wp-content\/uploads\/2018\/12\/RasPiRGBExternalWiring-300x250.png 300w\" sizes=\"(max-width: 811px) 100vw, 811px\" \/><\/a><p id=\"caption-attachment-410\" class=\"wp-caption-text\">External Power LED Wiring<\/p><\/div>\n<p>Do not connect the 5V to the Raspberry Pi (unless you know what you are doing, and it is the <strong>only<\/strong> power supply to the Raspberry Pi (i.e. there is no micro USB connected)).<\/p>\n<p>Remember that each LED could draw up to 60mA and ensure that your selected LED power supply is able to provide sufficient current to power all of your LEDs. Given that the supply is at 5v, this means you are looking for 5&#215;0.06 = 0.3 watts per LED. For example, if you had 100 LEDs, you would need a power supply rated to at least 30 watts at 5v.<\/p>\n<h6>5v Data Signal<\/h6>\n<p>Another potential issue which has not impacted me, is due to the Raspberry Pi sending data to the LEDs at 3.3v. I believe that the minimum voltage required by the LEDs when running at 5v is 3v and 3.3v does not give much overhead. This is likely to result in issues when longer wires result in a further reduction in voltage, potentially causing intermittent issues or complete failure to operate.<\/p>\n<p>This can be solved by voltage shifting the Raspberry Pi output using a MOSFET. The following method is actually a way of getting bi-directional level shifting (very useful for I2C), but is simple enough that we might as well use it here. I&#8217;ve based the circuit on the one here : <a href=\"http:\/\/www.hobbytronics.co.uk\/mosfet-voltage-level-converter\">http:\/\/www.hobbytronics.co.uk\/mosfet-voltage-level-converter<\/a>, please double check that my implementation is correct! Note the strip board could be smaller in reality (you could manage a 4&#215;3!), but I couldn&#8217;t get Fritzing to show stood up resistors.<\/p>\n<div id=\"attachment_413\" style=\"width: 779px\" class=\"wp-caption aligncenter\"><a href=\"https:\/\/elephantandchicken.co.uk\/stuffandnonsense\/wp-content\/uploads\/2018\/12\/RasPiRGBMOSFET.png\"><img aria-describedby=\"caption-attachment-413\" loading=\"lazy\" class=\"size-full wp-image-413\" src=\"https:\/\/elephantandchicken.co.uk\/stuffandnonsense\/wp-content\/uploads\/2018\/12\/RasPiRGBMOSFET.png\" alt=\"MOSFET LED Wiring\" width=\"769\" height=\"764\" srcset=\"https:\/\/elephantandchicken.co.uk\/stuffandnonsense\/wp-content\/uploads\/2018\/12\/RasPiRGBMOSFET.png 769w, https:\/\/elephantandchicken.co.uk\/stuffandnonsense\/wp-content\/uploads\/2018\/12\/RasPiRGBMOSFET-150x150.png 150w, https:\/\/elephantandchicken.co.uk\/stuffandnonsense\/wp-content\/uploads\/2018\/12\/RasPiRGBMOSFET-300x298.png 300w\" sizes=\"(max-width: 769px) 100vw, 769px\" \/><\/a><p id=\"caption-attachment-413\" class=\"wp-caption-text\">MOSFET LED Wiring<\/p><\/div>\n<p>Note that the orange wire is connected to a 3.3v pin on the Raspberry Pi. As labelled, the pinout for the 2N7000 MOSFET is Source, Gate, Drain from left to right, with the flat on the package facing you.<\/p>\n<h6>Future Project<\/h6>\n<p>The next thing I&#8217;d like to do is write a program to allow me to draw animations for an n by n LED matrix and save them in this image format. It shouldn&#8217;t be too difficult and would be fun and interesting. I don&#8217;t have a significant sized LED matrix though &#8211; I think the biggest I have is only an 8&#215;8.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Writing LED sequences can be quite a faff when you&#8217;re making your own programs and hardware. I decided that a handy way of visualising the patterns would be&#8230; to visualise them, as an image. To do this, I&#8217;ve written a simple program that takes a bitmap image and outputs the colours of each pixel in [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":416,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"spay_email":"","jetpack_publicize_message":"","jetpack_is_tweetstorm":false},"categories":[13,42,12,5],"tags":[128,131,111,129,130,9,127,126,125],"jetpack_featured_media_url":"https:\/\/elephantandchicken.co.uk\/stuffandnonsense\/wp-content\/uploads\/2018\/12\/exampleReallyBig.png","jetpack_publicize_connections":[],"jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/p7g9vY-6q","_links":{"self":[{"href":"https:\/\/elephantandchicken.co.uk\/stuffandnonsense\/index.php?rest_route=\/wp\/v2\/posts\/398"}],"collection":[{"href":"https:\/\/elephantandchicken.co.uk\/stuffandnonsense\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/elephantandchicken.co.uk\/stuffandnonsense\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/elephantandchicken.co.uk\/stuffandnonsense\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/elephantandchicken.co.uk\/stuffandnonsense\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=398"}],"version-history":[{"count":10,"href":"https:\/\/elephantandchicken.co.uk\/stuffandnonsense\/index.php?rest_route=\/wp\/v2\/posts\/398\/revisions"}],"predecessor-version":[{"id":417,"href":"https:\/\/elephantandchicken.co.uk\/stuffandnonsense\/index.php?rest_route=\/wp\/v2\/posts\/398\/revisions\/417"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/elephantandchicken.co.uk\/stuffandnonsense\/index.php?rest_route=\/wp\/v2\/media\/416"}],"wp:attachment":[{"href":"https:\/\/elephantandchicken.co.uk\/stuffandnonsense\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=398"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/elephantandchicken.co.uk\/stuffandnonsense\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=398"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/elephantandchicken.co.uk\/stuffandnonsense\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=398"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}