diff --git a/README.md b/README.md index 935a973..24e3578 100644 --- a/README.md +++ b/README.md @@ -1,358 +1,365 @@ -# PaPiRus -You can find here a variety of software, hardware and other resources for the [PaPiRus](http://papirus.ws) range of ePaper eInk displays from [Pi Supply](https://www.pi-supply.com). This repository is based on, and makes use of, the [rePaper/gratis GitHub repository](https://github.com/repaper/gratis). - -You can purchase one of the PaPiRus boards from [our webshop](https://www.pi-supply.com/?s=papirus&post_type=product&tags=1&limit=5&ixwps=1) or from a variety of resellers worldwide. - -# Setup PaPiRus -## Auto Installation -Just run the following script in a terminal window and PaPiRus will be automatically setup. -```bash -# Run this line and PaPiRus will be setup and installed -curl -sSL https://pisupp.ly/papiruscode | sudo bash -``` - -## Manual Installation -If you have any troubles with the auto installation or if for some reason you prefer to install PaPiRus manually, then follow the steps below. -#### Enabling SPI and I2C interfaces on Raspberry Pi -Before using PaPiRus, do not forget to enable the SPI and the I2C interfaces. -You can enable the SPI by typing `sudo raspi-config` at the command line and then selecting `Interfacing options` > `SPI` and then selecting Enable. Without exiting the tool still in `Interfacing options` > `I2C` and then selecting Enable. -#### Install Python API (best to run all of these commands as root using sudo) -```bash -# Install dependencies -apt-get install git -y -apt-get install python-imaging -y -apt-get install python-smbus -y -apt-get install bc i2c-tools -y -apt-get install python-dateutil -y - -git clone https://github.com/PiSupply/PaPiRus.git -cd PaPiRus -sudo python setup.py install # Install PaPirRus python library -``` - -#### Install Driver (Option 1) (best to run all of these commands as root using sudo) -```bash -sudo papirus-setup # This will auto install the driver -``` - -#### Install Driver (Option 2) (best to run all of these commands as root using sudo) -```bash -# Install fuse driver -sudo apt-get install libfuse-dev -y - -mkdir /tmp/papirus -cd /tmp/papirus -git clone https://github.com/repaper/gratis.git - -cd /tmp/papirus/gratis -make rpi EPD_IO=epd_io.h PANEL_VERSION='V231_G2' -make rpi-install EPD_IO=epd_io.h PANEL_VERSION='V231_G2' -systemctl enable epd-fuse.service -systemctl start epd-fuse -``` - -#### Select your screen size -```bash -sudo papirus-set [1.44 | 1.9 | 2.0 | 2.6 | 2.7 ] -or -sudo papirus-config -``` - -# Python API - -#### The Basic API - -```python -from papirus import Papirus - -# The epaper screen object. -# Optional rotation argument: rot = 0, 90, 180 or 270 -screen = Papirus([rotation = rot]) - -# Write a bitmap to the epaper screen -screen.display('./path/to/bmp/image') - -# Perform a full update to the screen (slower) -screen.update() - -# Update only the changed pixels (faster) -screen.partial_update() - -# Disable automatic use of LM75B temperature sensor -screen.use_lm75b = False - -# Change screen size -# SCREEN SIZES 1_44INCH | 1_9INCH | 2_0INCH | 2_6INCH | 2_7INCH -screen.set_size(papirus.2_7INCH) (coming soon) - -``` - -#### The Text API -```python -from papirus import PapirusText - -text = PapirusText([rotation = rot]) - -# Write text to the screen -# text.write(text) -text.write("hello world") -``` - -#### The Positional Text API (example 1) -```python -from papirus import PapirusTextPos - -# Same as calling "PapirusTextPos(True [,rotation = rot])" -text = PapirusTextPos([rotation = rot]) - -# Write text to the screen at selected point, with an Id -# "hello world" will appear on the screen at (10, 10), font size 20, straight away -text.AddText("hello world", 10, 10, Id="Start" ) - -# Add another line of text, at the default location -# "Another line" will appear on screen at (0, 0), font size 20, straight away -text.AddText("Another line", Id="Top") - -# Update the first line -# "hello world" will disappear and "New Text" will be displayed straight away -text.UpdateText("Start", "New Text") - -# Remove The second line of text -# "Another line" will be removed from the screen straight away -text.RemoveText("Top") - -# Clear all text from the screen -# This does a full update so is a little slower than just removing the text. -text.Clear() -``` - -#### The Positional Text API (example 2) -```python -from papirus import PapirusTextPos - -# Calling PapirusTextPos this way will mean nothing is written to the screen be default -text = PapirusTextPos(False [,rotation = rot]) - -# Write text to the screen at selected point, with an Id -# Nothing will show on the screen -text.AddText("hello world", 10, 10, Id="Start" ) - -# Add another line of text, at the default location -# Nothing will show on the screen -text.AddText("Another line", Id="Top") - -# Now display BOTH lines on the scrren -text.WriteAll() - -# Update the first line -# No change will happen on the screen -text.UpdateText("Start", "New Text") - -# Remove The second line of text -# The text won't be removed just yet from the screen -text.RemoveText("Top") - -# Now update the screen to show the changes -text.WriteAll() -``` - -#### The Positional Text API (example 3) -```python -from papirus import PapirusTextPos - -# Same as calling "PapirusTextPos(True)" -text = PapirusTextPos() - -# Write text to the screen at selected point, with an Id -# This will write "hello world" to the screen with white text and a black background -text.AddText("hello world", 10, 10, Id="Start", invert=True) -``` - -#### Notes -PaPiRusTextPos will take into account \n as a line break (or multiple line breaks) -Meaning text will be aligned to the X position given, it will not return to x=0 for the start of the next line. - -When using the PapirusTextPos, in either mode, setting the "partial_updates" property to True will cause partial updates to be done, meaning only the section of the PaPiRus screen that has been changed will be updated. These can be vastly quicker than a full update for each piece of text. - -If not using the "partial_updates" property, calling "WriteAll(True)" will do the same thing on a one off basis. - -#### Unicode Support in the Text API -```python -from papirus import PapirusText - -text = PapirusText() - -# Write text to the screen, in this case forty stars alternating black and white -# note the use of u"" syntax to specify unicode -text.write(u"\u2605 \u2606 \u2605 \u2606 \u2605 \u2606 \u2605 \u2606 \u2605 \u2606 \u2605 \u2606 \u2605 \u2606 \u2605 \u2606 \u2605 \u2606 \u2605 \u2606 \u2605 \u2606 \u2605 \u2606 \u2605 \u2606 \u2605 \u2606 \u2605 \u2606 \u2605 \u2606 \u2605 \u2606 \u2605 \u2606 \u2605 \u2606 \u2605 \u2606") -``` -#### Note -The default font, FreeMono, has [limited unicode support](http://www.fileformat.info/info/unicode/font/freemono/blocklist.htm), so you may want to specify an alternate font to use a fuller range characters. - -#### The Image API -```python -from papirus import PapirusImage - -image = PapirusImage([rotation = rot]) - -# easy write image to screen -# image.write(path) -image.write('/path/to/image') - -# write image to the screen with size and position -# image.write(path, width, (x,y)) -image.write('/path/to/image', 20, (10, 10) ) # This is not confirmed to work correctly yet!! -``` - -#### The composite API (Text and image) -```python -from papirus import PapirusComposite - -# Calling PapirusComposite this way will mean nothing is written to the screen until WriteAll is called -textNImg = PapirusComposite(False) - -# Write text to the screen at selected point, with an Id -# Nothing will show on the screen -textNImg.AddText("hello world", 10, 10, Id="Start" ) - -# Add image -# Nothing will show on the screen -# textNImg.AddImg(path, posX,posY,(w,h),id) -textNImg.AddImg("/path/to/image",20,20,(25,25), Id="BigImg") - -# Add image to the default place and size -# Nothing will show on the screen -textNImg.AddImg("/path/to/image", Id="Top") - -# Now display all elements on the scrren -textNImg.WriteAll() - -# Update the first line -# No change will happen on the screen -textNImg.UpdateText("Start", "New Text") - -# Update the BigImg -# No change will happen on the screen -textNImg.UpdateImg("BigImg", "/path/to/new/images") - -# Remove top image -# The images won't be removed just yet from the screen -textNImg.RemoveImg("Top") - -# Now update the screen to show the changes -textNImg.WriteAll() -``` - -#### Font family -PaPiRusText and PaPiRusTextPos are using the font _FreeMono.ttf_ by default. It is possible to specify the argument `font_path` in `PapirusText.write`, `PapirusTextPos.AddText`, `PapirusTextPos.UpdateText` and `PapirusTextPos.addToImageText` to change the _font family_. The argument must be a string containing the path to the _.ttf_ file. -``` -# Change font family -from papirus import PapirusText -text = PapirusText() -text.write("Hello World", fontPath='/path/to/ttf') -``` - -# Command Line - -```bash -# Set the screen size you are using -papirus-set [1.44 | 1.9 | 2.0 | 2.6 | 2.7 ] - -# Write data to the screen -papirus-write "Some text to write" [-x ] [-y ] [-fsize ] [-rot] [-inv] - -# Draw image on the screen -papirus-draw /path/to/image -t [resize | crop] -r [0 | 90 | 180 | 270] - -# Clear the screen -papirus-clear - -``` - -#### Demos -All demos can be seen by running the following commands. Code can be found in the repo for the python bin directory. - -```bash -# Board and screen diagnostic -papirus-test - -# Show clock -papirus-clock [rotation] - -# Run game of life -papirus-gol - -# Show system information -papirus-system - -# Push framebuffer to screen -papirus-framepush (coming soon) - -# Demo of using the buttons -papirus-buttons [rotation] - -# Demo of getting temperature from LM75 -papirus-temp - -# Demo showing dependency of update rate on temperature -papirus-radar - -# Display text filling the width of the display -papirus-textfill 'Some text' [rotation] - -# Snakes game -papirus-snakes (coming soon) - -# Display Twitter feeds -papirus-twitter - -# Composite text and graphics -papirus-composite-write -``` - -### Tips for using images -The PaPiRus can only display Bitmap images (.BMP) in black and white (1 bit colour). If you pass an image to PaPiRus that is not a 1 Bit Bitmap, it will automatically be converted to this by the software. However, for best results and higher image quality we would recommend that you convert the image to a 1 Bit Bitmap before pushing to the PaPiRus screen using GIMP or Photoshop or similar photo editing tools like [the rePaper companion](https://github.com/aerialist/repaper_companion) to resize images and convert them to XBM format or [WIF (the WyoLum Image Format)](http://wyolum.com/introducing-wif-the-wyolum-image-format/). - -### Screen Resolutions -The screens have the following screen resolutions: -``` -1.44" 128 x 96 -1.9" 144 x 128 -2.0" 200 x 96 -2.6" 232 x 128 -2.7" 264 x 176 -``` - -### Refresh rates and screen lifespan -A typical ePaper refresh rate for a full-screen update is around 1 to 2 Hz (1 to 2 updates per second). The refresh rate of the ePaper displays is dependent on a number of factors including temperature. At lower temperatures you have to drive the display more slowly otherwise you can get "ghosting" and also can damage the display. By fiddling with the temperature variables we have had customers who we know have got this level to ~15 Hz but this is not advised unless you know what you are doing as it will severely reduce the life of the display and may cause other bizarre side-effects. - -Lastly, a good way to increase the refresh rate of information on the screen is to not use full screen updates but use partial updates as described below. - -### Full and Partial Updates -Also try using the method partialUpdate() instead of the update() one if you want to refresh the screen faster and maybe want to create some simple animations. Remember though that the partial method cannot be used indefinitely and you will have to refresh the screen every once in a while. You should ideally do a full refresh of the screen every few minutes and it is also recommended to completely power down the screen every few hours. - - -# Hardware tips -In case you have problems assembling the board please [check this article on our website](https://www.pi-supply.com/make/papirus-assembly-tips-and-gotchas/) on which you can find: -* Connect the screen to the PaPiRus board -* Connect the GPIO adapter -* Install the pogo pin connector -* Install the push buttons - -Please note: Not all the sections apply to both the PaPiRus HAT and the PaPiRus Zero. - -### Datasheets, connectivity, pinout, jumpers and further information -For additional information follow the links below: -* [PaPiRus HAT](https://github.com/PiSupply/PaPiRus/tree/master/hardware/PaPiRus%20HAT) -* [PaPiRus Zero](https://github.com/PiSupply/PaPiRus/tree/master/hardware/PaPiRus%20Zero) -* [Pinout.xyz resources](https://pinout.xyz/boards#manufacturer=Pi%20Supply) - -# Third party software libraries - -It is safe to say we have an awesome and growing community of people using epaper with PaPiRus and beyond and we get a huge amount of contributions of code, some of which we can easily integrate here and others which we can't (we are only a small team). However we want to make sure that any contributions are easy to find, for anyone looking. So here is a list of other software libraries that might be useful to you (if you have one of your own, please visit the ["Issues"](https://github.com/PiSupply/PaPiRus/issues) tab above and let us know!): - -* [Go software library for driving PaPiRus](https://github.com/wmarbut/go-epdfuse) -* [RISC OS software library for driving PaPiRus](https://www.riscosopen.org/forum/forums/1/topics/9142?page=1) -* [PaPiRus HAT working with resin.io](https://github.com/resin-io-playground/resinio-PaPiRus) -* [Raspberry Pi Internal Watchdog Setup and Information](http://www.switchdoc.com/2014/11/reliable-projects-using-internal-watchdog-timer-raspberry-pi/) -* [Baseball Pi - get the live box score, plays, and batter stats of your favorite MLB team right on your desktop](https://github.com/eat-sleep-code/baseball-pi) +# PaPiRus +You can find here a variety of software, hardware and other resources for the [PaPiRus](http://papirus.ws) range of ePaper eInk displays from [Pi Supply](https://www.pi-supply.com). This repository is based on, and makes use of, the [rePaper/gratis GitHub repository](https://github.com/repaper/gratis). + +You can purchase one of the PaPiRus boards from [our webshop](https://www.pi-supply.com/?s=papirus&post_type=product&tags=1&limit=5&ixwps=1) or from a variety of resellers worldwide. + +# Setup PaPiRus +## Auto Installation +Just run the following script in a terminal window and PaPiRus will be automatically setup. +```bash +# Run this line and PaPiRus will be setup and installed +curl -sSL https://pisupp.ly/papiruscode | sudo bash +``` + +## Manual Installation +If you have any troubles with the auto installation or if for some reason you prefer to install PaPiRus manually, then follow the steps below. +#### Enabling SPI and I2C interfaces on Raspberry Pi +Before using PaPiRus, do not forget to enable the SPI and the I2C interfaces. +You can enable the SPI by typing `sudo raspi-config` at the command line and then selecting `Interfacing options` > `SPI` and then selecting Enable. Without exiting the tool still in `Interfacing options` > `I2C` and then selecting Enable. +#### Install Python API (best to run all of these commands as root using sudo) +```bash +# Install dependencies +apt-get install git -y +apt-get install python-imaging -y +apt-get install python-smbus -y +apt-get install bc i2c-tools -y +apt-get install python-dateutil -y + +git clone https://github.com/PiSupply/PaPiRus.git +cd PaPiRus +sudo python setup.py install # Install PaPirRus python library +``` + +#### Install Driver (Option 1) (best to run all of these commands as root using sudo) +```bash +sudo papirus-setup # This will auto install the driver +``` + +#### Install Driver (Option 2) (best to run all of these commands as root using sudo) +```bash +# Install fuse driver +sudo apt-get install libfuse-dev -y + +mkdir /tmp/papirus +cd /tmp/papirus +git clone https://github.com/repaper/gratis.git + +cd /tmp/papirus/gratis +make rpi EPD_IO=epd_io.h PANEL_VERSION='V231_G2' +make rpi-install EPD_IO=epd_io.h PANEL_VERSION='V231_G2' +systemctl enable epd-fuse.service +systemctl start epd-fuse +``` + +#### Select your screen size +```bash +sudo papirus-set [1.44 | 1.9 | 2.0 | 2.6 | 2.7 ] +or +sudo papirus-config +``` + +# Python API + +#### The Basic API + +```python +from papirus import Papirus + +# The epaper screen object. +# Optional rotation argument: rot = 0, 90, 180 or 270 +screen = Papirus([rotation = rot]) + +# Write a bitmap to the epaper screen +screen.display('./path/to/bmp/image') + +# Perform a full update to the screen (slower) +screen.update() + +# Update only the changed pixels (faster) +screen.partial_update() + +# Update only the changed pixels with user defined update duration +screen.fast_update() + +# Disable automatic use of LM75B temperature sensor +screen.use_lm75b = False + +``` + +#### The Text API +```python +from papirus import PapirusText + +text = PapirusText([rotation = rot]) + +# Write text to the screen +# text.write(text) +text.write("hello world") +``` + +#### The Positional Text API (example 1) +```python +from papirus import PapirusTextPos + +# Same as calling "PapirusTextPos(True [,rotation = rot])" +text = PapirusTextPos([rotation = rot]) + +# Write text to the screen at selected point, with an Id +# "hello world" will appear on the screen at (10, 10), font size 20, straight away +text.AddText("hello world", 10, 10, Id="Start" ) + +# Add another line of text, at the default location +# "Another line" will appear on screen at (0, 0), font size 20, straight away +text.AddText("Another line", Id="Top") + +# Update the first line +# "hello world" will disappear and "New Text" will be displayed straight away +text.UpdateText("Start", "New Text") + +# Remove The second line of text +# "Another line" will be removed from the screen straight away +text.RemoveText("Top") + +# Clear all text from the screen +# This does a full update so is a little slower than just removing the text. +text.Clear() +``` + +#### The Positional Text API (example 2) +```python +from papirus import PapirusTextPos + +# Calling PapirusTextPos this way will mean nothing is written to the screen be default +text = PapirusTextPos(False [,rotation = rot]) + +# Write text to the screen at selected point, with an Id +# Nothing will show on the screen +text.AddText("hello world", 10, 10, Id="Start" ) + +# Add another line of text, at the default location +# Nothing will show on the screen +text.AddText("Another line", Id="Top") + +# Now display BOTH lines on the scrren +text.WriteAll() + +# Update the first line +# No change will happen on the screen +text.UpdateText("Start", "New Text") + +# Remove The second line of text +# The text won't be removed just yet from the screen +text.RemoveText("Top") + +# Now update the screen to show the changes +text.WriteAll() +``` + +#### The Positional Text API (example 3) +```python +from papirus import PapirusTextPos + +# Same as calling "PapirusTextPos(True)" +text = PapirusTextPos() + +# Write text to the screen at selected point, with an Id +# This will write "hello world" to the screen with white text and a black background +text.AddText("hello world", 10, 10, Id="Start", invert=True) +``` + +#### Notes +PapirusTextPos will take into account \n as a line break (or multiple line breaks) +Meaning text will be aligned to the X position given, it will not return to x=0 for the start of the next line. + +WHen the text is longer than will fit on a single line, PapirusTextPos will break the text in multiple lines. +You can limit the number of lines by specifying the parameter `maxLines` in the `AddText()` method. + +When using the PapirusTextPos, in either mode, setting the "partialUpdates" property to True will cause partial updates to be done, meaning only the section of the PaPiRus screen that has been changed will be updated. These can be vastly quicker than a full update for each piece of text. + +If not using the "partialUpdates" property, calling `WriteAll(True)` will do the same thing on a one off basis. + +#### Unicode Support in the Text API +```python +from papirus import PapirusText + +text = PapirusText() + +# Write text to the screen, in this case forty stars alternating black and white +# note the use of u"" syntax to specify unicode +text.write(u"\u2605 \u2606 \u2605 \u2606 \u2605 \u2606 \u2605 \u2606 \u2605 \u2606 \u2605 \u2606 \u2605 \u2606 \u2605 \u2606 \u2605 \u2606 \u2605 \u2606 \u2605 \u2606 \u2605 \u2606 \u2605 \u2606 \u2605 \u2606 \u2605 \u2606 \u2605 \u2606 \u2605 \u2606 \u2605 \u2606 \u2605 \u2606 \u2605 \u2606") +``` +#### Note +The default font, FreeMono, has [limited unicode support](http://www.fileformat.info/info/unicode/font/freemono/blocklist.htm), so you may want to specify an alternate font to use a fuller range characters. + +#### The Image API +```python +from papirus import PapirusImage + +image = PapirusImage([rotation = rot]) + +# easy write image to screen +# image.write(path) +image.write('/path/to/image') + +# write image to the screen with size and position +# image.write(path, width, (x,y)) +image.write('/path/to/image', 20, (10, 10) ) # This is not confirmed to work correctly yet!! +``` + +#### The composite API (Text and image) +```python +from papirus import PapirusComposite + +# Calling PapirusComposite this way will mean nothing is written to the screen until WriteAll is called +textNImg = PapirusComposite(False [, rotation = rot]) + +# Write text to the screen at selected point, with an Id +# Nothing will show on the screen +textNImg.AddText("hello world", 10, 10, Id="Start" ) + +# Add image +# Nothing will show on the screen +# textNImg.AddImg(path, posX,posY,(w,h),id) +textNImg.AddImg("/path/to/image",20,20,(25,25), Id="BigImg") + +# Add image to the default place and size +# Nothing will show on the screen +textNImg.AddImg("/path/to/image", Id="Top") + +# Now display all elements on the scrren +textNImg.WriteAll() + +# Update the first line +# No change will happen on the screen +textNImg.UpdateText("Start", "New Text") + +# Update the BigImg +# No change will happen on the screen +textNImg.UpdateImg("BigImg", "/path/to/new/images") + +# Remove top image +# The images won't be removed just yet from the screen +textNImg.RemoveImg("Top") + +# Now update the screen to show the changes +textNImg.WriteAll() +``` + +#### Font family +PaPiRusText and PaPiRusTextPos are using the font _FreeMono.ttf_ by default. It is possible to specify the argument `font_path` in `PapirusText.write`, `PapirusTextPos.AddText`, `PapirusTextPos.UpdateText` and `PapirusTextPos.addToImageText` to change the _font family_. The argument must be a string containing the path to the _.ttf_ file. +``` +# Change font family +from papirus import PapirusText +text = PapirusText() +text.write("Hello World", fontPath='/path/to/ttf') +``` + +# Command Line + +```bash +# Set the screen size you are using +papirus-set [1.44 | 1.9 | 2.0 | 2.6 | 2.7 ] + +# Write data to the screen +papirus-write "Some text to write" [-x ] [-y ] [-fsize ] [-rot] [-inv] + +# Draw image on the screen +papirus-draw /path/to/image -t [resize | crop] -r [0 | 90 | 180 | 270] + +# Clear the screen +papirus-clear + +``` + +#### Demos +All demos can be seen by running the following commands. Code can be found in the repo for the python bin directory. + +```bash +# Board and screen diagnostic +papirus-test + +# Show clock +papirus-clock [rotation] + +# Run game of life +papirus-gol + +# Show system information +papirus-system + +# Push framebuffer to screen +papirus-framepush (coming soon) + +# Demo of using the buttons +papirus-buttons [rotation] + +# Demo of getting temperature from LM75 +papirus-temp [rotation] + +# Demo showing effect of fast update +papirus-radar + +# Display text filling the width of the display +papirus-textfill 'Some text' [rotation] + +# Snakes game +papirus-snakes (coming soon) + +# Display Twitter feeds +papirus-twitter + +# Composite text and graphics +papirus-composite-write +``` + +### Tips for using images +The PaPiRus can only display Bitmap images (.BMP) in black and white (1 bit colour). If you pass an image to PaPiRus that is not a 1 Bit Bitmap, it will automatically be converted to this by the software. However, for best results and higher image quality we would recommend that you convert the image to a 1 Bit Bitmap before pushing to the PaPiRus screen using GIMP or Photoshop or similar photo editing tools like [the rePaper companion](https://github.com/aerialist/repaper_companion) to resize images and convert them to XBM format or [WIF (the WyoLum Image Format)](http://wyolum.com/introducing-wif-the-wyolum-image-format/). + +### Screen Resolutions +The screens have the following screen resolutions: +``` +1.44" 128 x 96 +1.9" 144 x 128 +2.0" 200 x 96 +2.6" 232 x 128 +2.7" 264 x 176 +``` + +### Refresh rates and screen lifespan +A typical ePaper refresh rate for a full-screen update is around 1 to 2 Hz (1 to 2 updates per second). The refresh rate of the ePaper displays is dependent on a number of factors including temperature. At lower temperatures you have to drive the display more slowly otherwise you can get "ghosting" and also can damage the display. + +Lastly, a good way to increase the refresh rate of information on the screen is to not use full screen updates but use partial updates as described below. + +### Full and Partial Updates +Also try using the method partial_update() instead of the update() one if you want to refresh the screen faster and maybe want to create some simple animations. Remember though that the partial method cannot be used indefinitely. +You should refresh the screen using a Full Update every few minutes and it is also recommended to completely power down the screen every few hours. + +### Fast Update +Fast Update works the same as Partial Update, except the refresh rate is not dependent on temperature but can be set by the user. The refresh duration for this mode is set in milliseconds by writing to `/dev/epd/pu_stagetime`. See the papirus-radar demo code for details. +Using this mode is only advised if you know what you are doing as it will severely reduce the life of the display and may cause other bizarre side-effects. +As with the Partial Update mode you should refresh the screen using a Full Update every few minutes and it is also recommended to completely power down the screen every few hours. + +# Hardware tips +In case you have problems assembling the board please [check this article on our website](https://www.pi-supply.com/make/papirus-assembly-tips-and-gotchas/) on which you can find: +* Connect the screen to the PaPiRus board +* Connect the GPIO adapter +* Install the pogo pin connector +* Install the push buttons + +Please note: Not all the sections apply to both the PaPiRus HAT and the PaPiRus Zero. + +### Datasheets, connectivity, pinout, jumpers and further information +For additional information follow the links below: +* [PaPiRus HAT](https://github.com/PiSupply/PaPiRus/tree/master/hardware/PaPiRus%20HAT) +* [PaPiRus Zero](https://github.com/PiSupply/PaPiRus/tree/master/hardware/PaPiRus%20Zero) +* [Pinout.xyz resources](https://pinout.xyz/boards#manufacturer=Pi%20Supply) + +# Third party software libraries + +It is safe to say we have an awesome and growing community of people using epaper with PaPiRus and beyond and we get a huge amount of contributions of code, some of which we can easily integrate here and others which we can't (we are only a small team). However we want to make sure that any contributions are easy to find, for anyone looking. So here is a list of other software libraries that might be useful to you (if you have one of your own, please visit the ["Issues"](https://github.com/PiSupply/PaPiRus/issues) tab above and let us know!): + +* [Go software library for driving PaPiRus](https://github.com/wmarbut/go-epdfuse) +* [RISC OS software library for driving PaPiRus](https://www.riscosopen.org/forum/forums/1/topics/9142?page=1) +* [PaPiRus HAT working with resin.io](https://github.com/resin-io-playground/resinio-PaPiRus) +* [Raspberry Pi Internal Watchdog Setup and Information](http://www.switchdoc.com/2014/11/reliable-projects-using-internal-watchdog-timer-raspberry-pi/) +* [Baseball Pi - get the live box score, plays, and batter stats of your favorite MLB team right on your desktop](https://github.com/eat-sleep-code/baseball-pi) diff --git a/bin/papirus-radar b/bin/papirus-radar old mode 100644 new mode 100755 index 1ad7829..a7c981d --- a/bin/papirus-radar +++ b/bin/papirus-radar @@ -1,26 +1,37 @@ #!/usr/bin/env python -# Demo showing the dependency of frame update duration on temperature +# Demo showing the effect of frame update duration (stagetime). # -# Fastest update is with temperature set to > 60, but ghosting is evident. -# Lower temperatures give blacker updates, with less ghosting. -# By not using the LM75B temperature sensor, we can fake the temperature by -# writing to /dev/epd/termperature +# Shortest update duration in the demo is 50 msec, but ghosting is evident. +# Larger update duration gives a blacker update, with less ghosting. +# A normal update duration when using partial update is 500 msec. # -# This demo is a modified version of David Lowe's original demo (https://github.com/campag/eink-demo) -# Best results with the epd driver with continous temperature compensation. +# This demo is based on David Lowe's original demo (https://github.com/campag/eink-demo), +# but uses the fast update mode where you can set the stagetime directly. -import thread -import string -import time +import os import sys from datetime import datetime, timedelta -from subprocess import call, check_output from PIL import Image from PIL import ImageDraw, ImageFont from papirus import Papirus +# Check EPD_SIZE is defined +EPD_SIZE=0.0 +if os.path.exists('/etc/default/epd-fuse'): + execfile('/etc/default/epd-fuse') +if EPD_SIZE == 0.0: + print("Please select your screen size by running 'papirus-config'.") + sys.exit() + +# Running as root only needed for older Raspbians without /dev/gpiomem +if not (os.path.exists('/dev/gpiomem') and os.access('/dev/gpiomem', os.R_OK | os.W_OK)): + user = os.getuid() + if user != 0: + print("Please run script as root") + sys.exit() + epd = Papirus() SCREEN_WIDTH = epd.size[0] @@ -29,9 +40,9 @@ SCREEN_HEIGHT = epd.size[1] SCREEN_WIDTH-=1 SCREEN_HEIGHT-=1 -FONTFILE = '/usr/share/fonts/truetype/freefont/FreeMonoBold.ttf' +FONTFILE = '/usr/share/fonts/truetype/freefont/FreeSans.ttf' -SIZE_MED = int(SCREEN_HEIGHT/4) #24 +SIZE_MED = int(SCREEN_HEIGHT/4) FONT_MED = ImageFont.truetype(FONTFILE, SIZE_MED) CHRW_MED = FONT_MED.getsize("0")[0] @@ -43,7 +54,7 @@ DURATION = 15 # seconds image = Image.new('1', epd.size, WHITE) draw = ImageDraw.Draw(image) -def epd_draw(lagtime, packet_num): +def epd_draw(starttime, cycletime, packet_num): # Clear drawing draw.rectangle([(0,0), (SCREEN_WIDTH, SCREEN_HEIGHT)], fill=WHITE, outline=WHITE) @@ -52,39 +63,40 @@ def epd_draw(lagtime, packet_num): draw.ellipse([((SCREEN_WIDTH-SCREEN_HEIGHT)/2,0),(SCREEN_HEIGHT+(SCREEN_WIDTH-SCREEN_HEIGHT)/2, SCREEN_HEIGHT)], outline=BLACK) draw.pieslice([((SCREEN_WIDTH-SCREEN_HEIGHT)/2,0),(SCREEN_HEIGHT+(SCREEN_WIDTH-SCREEN_HEIGHT)/2, SCREEN_HEIGHT)], 10*packet_num-2, 10*packet_num+2, fill=BLACK) - # Temperature & seconds counter - temp=check_output(["cat", "/dev/epd/temperature"]) - temp=temp[:-1]+u'\u00b0C' + # Stagetime & seconds counter + with open('/dev/epd/pu_stagetime','r') as f: + stagetime = f.read().rstrip('\n') now = datetime.today() - draw.text((SCREEN_WIDTH/2-5.0*CHRW_MED, SCREEN_HEIGHT/2-1.5*SIZE_MED), "%s %02ds" %(temp, now.second), fill=BLACK, font=FONT_MED) + seconds = (now - starttime).total_seconds() + draw.text((SCREEN_WIDTH/2-4.0*CHRW_MED, SCREEN_HEIGHT/2-1.5*SIZE_MED), "%s %02ds" %(stagetime, seconds), fill=BLACK, font=FONT_MED) # fps - fps10x=10000/lagtime - draw.text((SCREEN_WIDTH/2-3.0*CHRW_MED, SCREEN_HEIGHT/2-0.5*SIZE_MED), "%3dfps" %fps10x, fill=BLACK, font=FONT_MED) - draw.text((SCREEN_WIDTH/2-1.4*CHRW_MED, SCREEN_HEIGHT/2-0.5*SIZE_MED), ".", fill=BLACK, font=FONT_MED) + fpsint = 1000/cycletime + fpsfract = 10000/cycletime - fpsint*10 + draw.text((SCREEN_WIDTH/2-3.0*CHRW_MED, SCREEN_HEIGHT/2-0.5*SIZE_MED), "%02d.%1dfps" %(fpsint, fpsfract), fill=BLACK, font=FONT_MED) # Cycle time - draw.text((SCREEN_WIDTH/2-2.5*CHRW_MED, SCREEN_HEIGHT/2+0.5*SIZE_MED), "%3dms" %lagtime, fill=BLACK, font=FONT_MED) + draw.text((SCREEN_WIDTH/2-2.5*CHRW_MED, SCREEN_HEIGHT/2+0.5*SIZE_MED), "%03dms" %cycletime, fill=BLACK, font=FONT_MED) # Swap rendered image to epd image buffer epd.display(image) - if lagtime > 0: - epd.partial_update() + if cycletime > 0: + epd.fast_update() return # Main entry -temps = [25, 35, 45, 55, 65] -for temp in temps: +times = [500, 200, 100, 75, 50] # stagetimes in msec +for time in times: epd.use_lm75b = True epd.clear() epd.use_lm75b = False - # Set temperature - cmd = "echo " + str(temp) + " > /dev/epd/temperature" - call([cmd], shell=True) + # Set stagetime + with open('/dev/epd/pu_stagetime', 'wb') as f: + f.write(str(time)) counter=0 frametime=-1 # No screen update for first frame @@ -94,7 +106,7 @@ for temp in temps: delta = timedelta(seconds = DURATION) while (True): prev=datetime.now() - epd_draw(frametime,counter) + epd_draw(starttime,frametime,counter) curr=datetime.now() if (curr - starttime) > delta: break @@ -102,10 +114,7 @@ for temp in temps: counter += 1 except KeyboardInterrupt: print "\nClearing panel for long term storage" - epd.use_lm75b = True - epd.clear() - epd.clear() - sys.exit('\nKeyboard interrupt') + break; epd.use_lm75b = True epd.clear() diff --git a/bin/papirus-temp b/bin/papirus-temp index d19d552..fa85382 100644 --- a/bin/papirus-temp +++ b/bin/papirus-temp @@ -28,7 +28,8 @@ if not (os.path.exists('/dev/gpiomem') and os.access('/dev/gpiomem', os.R_OK | o WHITE = 1 BLACK = 0 -FONT_FILE = '/usr/share/fonts/truetype/freefont/FreeMono.ttf' +#FONT_FILE = '/usr/share/fonts/truetype/freefont/FreeMono.ttf' +FONT_FILE = '/usr/share/fonts/truetype/freefont/FreeSerif.ttf' def main(argv): @@ -44,16 +45,23 @@ def main(argv): draw = ImageDraw.Draw(image) width, height = image.size + # base font size on mono spaced font font_size = int((width - 4) / (8 * 0.65)) # 8 chars to be displayed font = ImageFont.truetype(FONT_FILE, font_size) + # get temperature sensor = LM75B() - - print('Temperature from LM75B: {c:.2f}'.format(c=sensor.getTempCFloat()) + u"\u00b0" + "C - " + '{f:.2f}'.format(f=sensor.getTempFFloat()) + u"\u00b0" + "F") - + tempC = '{c:.2f}'.format(c=sensor.getTempCFloat()) + u" \u00b0" + 'C' + tempF = '{c:.2f}'.format(c=sensor.getTempFFloat()) + u" \u00b0" + 'F' + print('Temperature from LM75B: ' + tempC + ' - ' + tempF) + + # center the temperatures + (txtwidth, txtheight) = draw.textsize(tempC, font=font) + x = (width - txtwidth) / 2 + y = (height - 2 * txtheight - 10) / 2 draw.rectangle((2, 2, width - 2, height - 2), fill=WHITE, outline=BLACK) - draw.text((4, 4), '{t:.2f}\xb0 C'.format(t=sensor.getTempCFloat()), fill=BLACK, font=font) - draw.text((4, 14 + font_size), '{t:.2f}\xb0 F'.format(t=sensor.getTempFFloat()), fill=BLACK, font=font) + draw.text((x, y), tempC, fill=BLACK, font=font) + draw.text((x, y + txtheight + 5), tempF, fill=BLACK, font=font) papirus.display(image) papirus.update()