├── .gitignore ├── CMakeLists.txt ├── CONTRIBUTING.md ├── DOC ├── HTML │ ├── images │ │ ├── LDR-fritz.png │ │ ├── LDR-gnup-1.png │ │ ├── LDR-gnup-2.png │ │ ├── LDR-photo.jpg │ │ ├── LDR-wave-1.png │ │ ├── LDR-wave-2.png │ │ ├── LDR-wave-3.png │ │ ├── breadboard.jpg │ │ ├── caps.jpg │ │ ├── driver.jpg │ │ ├── faq-i2c-ss.png │ │ ├── faq-i2c.jpg │ │ ├── faq-serial.jpg │ │ ├── faq-spi.jpg │ │ ├── faq1.jpg │ │ ├── faq2.jpg │ │ ├── faq3.jpg │ │ ├── imu-1.jpg │ │ ├── imu-2.jpg │ │ ├── imu-3.jpg │ │ ├── ir-fritz.png │ │ ├── ir-motion.jpg │ │ ├── ir-photo.jpg │ │ ├── ir-rx.jpg │ │ ├── ir-wave-1.png │ │ ├── ir-wave-2.png │ │ ├── ir-wave-3.png │ │ ├── keypad.jpg │ │ ├── lcd.jpg │ │ ├── ldr-cap.jpg │ │ ├── ldr.jpg │ │ ├── leds.jpg │ │ ├── meter.jpg │ │ ├── motor.jpg │ │ ├── msp430.jpg │ │ ├── nano.jpg │ │ ├── oled-2.jpg │ │ ├── oled.jpg │ │ ├── pigpio-logo.gif │ │ ├── pins.jpg │ │ ├── pisc-1.jpg │ │ ├── pisc-2.jpg │ │ ├── pisc-3.jpg │ │ ├── pot.jpg │ │ ├── pro-mini.jpg │ │ ├── psu.jpg │ │ ├── re-fritz.png │ │ ├── re-photo.jpg │ │ ├── re-wave-1.png │ │ ├── re-wave-2.png │ │ ├── remote-1.jpg │ │ ├── remote-2.jpg │ │ ├── reverse.jpg │ │ ├── rf-rx-2.jpg │ │ ├── rf-rx.jpg │ │ ├── rf-tx.jpg │ │ ├── rotary.jpg │ │ ├── rpi.jpg │ │ ├── serial.jpg │ │ ├── servo.jpg │ │ ├── sidebar.gif │ │ ├── son-fritz.png │ │ ├── son-gnup-1.png │ │ ├── son-gnup-2.png │ │ ├── son-photo.jpg │ │ ├── son-wave-1.png │ │ ├── son-wave-2.png │ │ ├── son-wave-3.png │ │ ├── son-wave-4.png │ │ ├── speaker.jpg │ │ ├── spi-lnx-pi3b.png │ │ ├── spi-lnx-pibr1.png │ │ ├── spi-pig-pi3b.png │ │ ├── spi-pig-pibr1.png │ │ ├── srf02.jpg │ │ ├── srf04.jpg │ │ ├── stepper.jpg │ │ ├── switches.jpg │ │ ├── topbar.gif │ │ ├── transistors.jpg │ │ ├── ubec-2.jpg │ │ ├── uln2003a.jpg │ │ ├── wheel.jpg │ │ ├── wires.jpg │ │ └── yl-40.jpg │ └── scripts │ │ ├── index.css │ │ └── standard.css ├── MAN │ └── README ├── README ├── bin │ ├── backup.sh │ ├── body.py │ ├── build_site.py │ ├── cmakdoc.py │ ├── examples.py │ ├── html.py │ ├── purge.sh │ ├── pymakdoc.py │ ├── smakdoc.py │ ├── tidy.py │ └── updatesql.py ├── dbase │ └── pigpio.sqlite ├── makedoc └── src │ ├── defs │ ├── examples.def │ ├── pig2vcd.def │ ├── pigpiod.def │ └── pigs.def │ └── html │ ├── download.html │ ├── ex_LDR.html │ ├── ex_ir_remote.html │ ├── ex_motor_shield.html │ ├── ex_rotary_encoder.html │ ├── ex_sonar_ranger.html │ ├── faq.html │ ├── index.html │ ├── misc.html │ ├── pif.html │ ├── piscope.html │ └── sif.html ├── EXAMPLES ├── C │ ├── COUNTER_1 │ │ ├── README │ │ └── freq_count_1.c │ ├── COUNTER_2 │ │ ├── README │ │ └── freq_count_2.c │ ├── HALL_EFFECT_SENSOR │ │ ├── README │ │ └── hall.c │ ├── I2C_SNIFFER │ │ ├── README │ │ └── pig2i2c.c │ ├── IR_RECEIVER │ │ ├── README │ │ ├── ir_hasher.c │ │ ├── ir_hasher.h │ │ └── test_ir_hasher.c │ ├── PCF8591_YL-40 │ │ ├── PCF8591.c │ │ └── README │ ├── POT_CAP_RECHARGE │ │ ├── README │ │ └── pot_cap_charge.c │ ├── ROTARY_ENCODER │ │ ├── README │ │ ├── rotary_encoder.c │ │ ├── rotary_encoder.h │ │ └── test_rotary_encoder.c │ └── WIEGAND_CODE │ │ ├── README │ │ ├── test_wiegand.c │ │ ├── wiegand.c │ │ └── wiegand.h ├── CPP │ ├── IR_RECEIVER │ │ ├── README │ │ ├── ir_hasher.cpp │ │ ├── ir_hasher.hpp │ │ └── test_ir_hasher.cpp │ ├── ROTARY_ENCODER │ │ ├── README │ │ ├── rotary_encoder.cpp │ │ ├── rotary_encoder.hpp │ │ └── test_rotary_encoder.cpp │ └── WIEGAND_CODE │ │ ├── README │ │ ├── test_wiegand.cpp │ │ ├── wiegand.cpp │ │ └── wiegand.hpp ├── Python │ ├── DHT11_SENSOR │ │ ├── README │ │ └── dht11.py │ ├── DHT22_AM2302_SENSOR │ │ ├── DHT22.py │ │ └── README │ ├── GPIO_STATUS │ │ ├── README │ │ └── gpio_status.py │ ├── HALL_EFFECT_SENSOR │ │ ├── README │ │ └── hall.py │ ├── I2C_SNIFFER │ │ ├── I2C_sniffer.py │ │ └── README │ ├── IR_RECEIVER │ │ ├── README │ │ └── ir_hasher.py │ ├── MORSE_CODE │ │ ├── README │ │ └── morse_code.py │ ├── PCF8591_YL-40 │ │ ├── PCF8591.py │ │ └── README │ ├── PIGPIO_BENCHMARK │ │ ├── README │ │ └── bench_1.py │ ├── ROTARY_ENCODER │ │ ├── README │ │ └── rotary_encoder.py │ ├── SENT_PROTOCOL │ │ ├── README.md │ │ └── read_SENT.py │ ├── SONAR_RANGER │ │ ├── README │ │ └── sonar_trigger_echo.py │ ├── VIRTUAL_WIRE │ │ ├── README │ │ └── vw.py │ └── WIEGAND_CODE │ │ ├── README │ │ └── wiegand.py └── Shell │ └── GPIOTEST │ ├── README │ └── gpiotest ├── MakeRemote ├── Makefile ├── README ├── README.md ├── SUPPORT.md ├── UNLICENCE ├── cmake ├── FindRT.cmake ├── pigpioConfig.cmake └── setup.py.in ├── command.c ├── command.h ├── custom.cext ├── pig2vcd.1 ├── pig2vcd.c ├── pigpio.3 ├── pigpio.c ├── pigpio.h ├── pigpio.py ├── pigpiod.1 ├── pigpiod.c ├── pigpiod_if.3 ├── pigpiod_if.c ├── pigpiod_if.h ├── pigpiod_if2.3 ├── pigpiod_if2.c ├── pigpiod_if2.h ├── pigs.1 ├── pigs.c ├── pigs.h ├── setup.py ├── util ├── Findpigpio.cmake ├── pigpiod.service └── readme.md ├── x_pigpio.c ├── x_pigpio.py ├── x_pigpiod_if.c ├── x_pigpiod_if2.c ├── x_pigs └── x_pipe /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *.so 3 | *.so.* 4 | *.pyc 5 | pig2vcd 6 | pigpiod 7 | pigs 8 | x_pigpio 9 | x_pigpiod_if 10 | x_pigpiod_if2 11 | __pycache__ 12 | build 13 | dist 14 | *.egg-info 15 | 16 | tmp/ 17 | 18 | # DOC files 19 | DOC/dbase/pigpio.sqlite.* 20 | DOC/tmp 21 | DOC/MAN/* 22 | !DOC/MAN/README* 23 | DOC/HTML/*.html 24 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.0) 2 | 3 | project(pigpio LANGUAGES C VERSION 0.71) 4 | 5 | list (APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}/cmake) 6 | 7 | find_package(Threads REQUIRED) 8 | find_package(RT REQUIRED) 9 | 10 | option(BUILD_SHARED_LIBS "Create shared libraries" ON) 11 | 12 | add_compile_options(-Wall) 13 | 14 | # libpigpio.(so|a) 15 | add_library(pigpio pigpio.c command.c custom.cext) 16 | 17 | # libpigpiod_if.(so|a) 18 | add_library(pigpiod_if pigpiod_if.c command.c) 19 | 20 | # libpigpiod_if2.(so|a) 21 | add_library(pigpiod_if2 pigpiod_if2.c command.c) 22 | 23 | # x_pigpio 24 | add_executable(x_pigpio x_pigpio.c) 25 | target_link_libraries(x_pigpio pigpio RT::RT Threads::Threads) 26 | 27 | # x_pigpiod_if 28 | add_executable(x_pigpiod_if x_pigpiod_if.c) 29 | target_link_libraries(x_pigpiod_if pigpiod_if RT::RT Threads::Threads) 30 | 31 | # x_pigpiod_if2 32 | add_executable(x_pigpiod_if2 x_pigpiod_if2.c) 33 | target_link_libraries(x_pigpiod_if2 pigpiod_if2 RT::RT Threads::Threads) 34 | 35 | # pigpiod 36 | add_executable(pigpiod pigpiod.c) 37 | target_link_libraries(pigpiod pigpio RT::RT Threads::Threads) 38 | 39 | # pigs 40 | add_executable(pigs pigs.c command.c) 41 | target_link_libraries(pigs Threads::Threads) 42 | 43 | # pig2vcd 44 | add_executable(pig2vcd pig2vcd.c command.c) 45 | target_link_libraries(pig2vcd Threads::Threads) 46 | 47 | # Configure and install project 48 | 49 | include (GenerateExportHeader) 50 | include (CMakePackageConfigHelpers) 51 | 52 | generate_export_header(${PROJECT_NAME}) 53 | 54 | install(TARGETS pigpio pigpiod_if pigpiod_if2 pig2vcd pigpiod pigs 55 | EXPORT ${PROJECT_NAME}Targets 56 | LIBRARY DESTINATION lib 57 | ARCHIVE DESTINATION lib 58 | RUNTIME DESTINATION bin 59 | INCLUDES DESTINATION include 60 | ) 61 | 62 | write_basic_package_version_file( 63 | "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake" 64 | VERSION ${${PROJECT_NAME}_VERSION} 65 | COMPATIBILITY AnyNewerVersion 66 | ) 67 | 68 | export(EXPORT ${PROJECT_NAME}Targets 69 | FILE "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Targets.cmake" 70 | NAMESPACE pigpio:: 71 | ) 72 | 73 | set(ConfigPackageLocation lib/cmake/${PROJECT_NAME}) 74 | install(EXPORT ${PROJECT_NAME}Targets 75 | FILE 76 | ${PROJECT_NAME}Targets.cmake 77 | NAMESPACE 78 | pigpio:: 79 | DESTINATION 80 | ${ConfigPackageLocation} 81 | ) 82 | 83 | install( 84 | FILES 85 | ${CMAKE_CURRENT_LIST_DIR}/cmake/${PROJECT_NAME}Config.cmake 86 | "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake" 87 | DESTINATION 88 | ${ConfigPackageLocation} 89 | ) 90 | 91 | install(FILES pigpio.h pigpiod_if.h pigpiod_if2.h 92 | DESTINATION include 93 | PERMISSIONS OWNER_READ OWNER_WRITE 94 | GROUP_READ 95 | WORLD_READ 96 | ) 97 | 98 | file(GLOB man_1_SRC "*.1") 99 | install(FILES ${man_1_SRC} 100 | DESTINATION man/man1 101 | PERMISSIONS OWNER_READ OWNER_WRITE 102 | GROUP_READ 103 | WORLD_READ 104 | ) 105 | 106 | file(GLOB man_3_SRC "*.3") 107 | install(FILES ${man_3_SRC} 108 | DESTINATION man/man3 109 | PERMISSIONS OWNER_READ OWNER_WRITE 110 | GROUP_READ 111 | WORLD_READ 112 | ) 113 | 114 | # Install python modules. 115 | find_package(Python COMPONENTS Interpreter QUIET) 116 | 117 | if(Python_FOUND) 118 | configure_file(${CMAKE_CURRENT_LIST_DIR}/cmake/setup.py.in 119 | ${CMAKE_CURRENT_BINARY_DIR}/setup.py 120 | ) 121 | 122 | install(CODE "execute_process(COMMAND ${Python_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/setup.py install)") 123 | endif() 124 | 125 | # package project 126 | 127 | include (CPack) -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | ## Submitting a New Issue 2 | If you are reporting a **bug** or defect, please provide the steps to reproduce the problem you are describing. 3 | Ideally, provide a simple script that will reproduce the issue. Also provide a description of the hardware and 4 | software types and versions used in your application/test environment. 5 | 6 | Requests for a feature or **enhancement** to the library software will be treated at a lower priority due to the lack 7 | of resources (contributors with skillset, knowledge of the library or time). Unless your request has wide support 8 | from the community it will be treated at a low priority. If the repo's maintainer judges your request to be of value 9 | then it will be labeled `enhancement`. If additional resources are required, it will be tagged with `help wanted`. 10 | 11 | If you simply have a **question**, consult the SUPPORT.md document. 12 | 13 | ## Creating a Pull Request 14 | Contributions are welcome. To save time it is best to have an open issue relating to what it is you want to contribute 15 | and to discuss the prospects of getting your contribution accepted. 16 | 17 | Your changes *must* pass the set of test files `x_*`. Please indicate that you have run the test scripts successfuly or attach 18 | a screen shot of the output from the test scripts. 19 | 20 | In addition, you *should* provide updated or additional scripts that at least test the 'happy' paths of your code changes. For 21 | larger changes the additional test cases will be considered mandatory. 22 | 23 | Beginning 2020, this repo will follow a dual branch model: `master` is the stable branch that people use in production. A second branch, `develop`, is the first branch to receive merges from bug fixes and new features. Only after we consider `develop` stable we merge it into the `master` branch and release the changes with a tagged version. 24 | 25 | Adhering to the following process is the best way to get your work included in the project: 26 | 27 | - Fork the project, clone your fork, and configure the remotes: 28 | ``` 29 | # Clone your fork of the repo into the current directory 30 | git clone https://github.com//pigio.git 31 | 32 | # Navigate to the newly cloned directory 33 | cd pigpio 34 | 35 | # Assign the original repo to a remote called "upstream" 36 | git remote add upstream https://github.com/joan2937/pigpio.git 37 | ``` 38 | - If you cloned a while ago, get the latest changes from upstream: 39 | ``` 40 | git checkout develop 41 | git pull upstream develop 42 | ``` 43 | - Create a new topic branch (off the develop branch) to contain your feature, change, or fix: 44 | ``` 45 | git checkout -b 46 | ``` 47 | - Commit your changes. 48 | 49 | - Locally merge (or rebase) the upstream dev branch into your topic branch: 50 | ``` 51 | git pull [--rebase] upstream develop 52 | ``` 53 | - Push your topic branch up to your fork: 54 | ``` 55 | git push origin 56 | ``` 57 | - Open a Pull Request with a clear title and description. See [creating a pull request from a fork](https://help.github.com/en/github/collaborating-with-issues-and-pull-requests/creating-a-pull-request-from-a-fork). 58 | Make sure the base branch drop down menu is selecting 'develop'. 59 | -------------------------------------------------------------------------------- /DOC/HTML/images/LDR-fritz.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joan2937/pigpio/c33738a320a3e28824af7807edafda440952c05d/DOC/HTML/images/LDR-fritz.png -------------------------------------------------------------------------------- /DOC/HTML/images/LDR-gnup-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joan2937/pigpio/c33738a320a3e28824af7807edafda440952c05d/DOC/HTML/images/LDR-gnup-1.png -------------------------------------------------------------------------------- /DOC/HTML/images/LDR-gnup-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joan2937/pigpio/c33738a320a3e28824af7807edafda440952c05d/DOC/HTML/images/LDR-gnup-2.png -------------------------------------------------------------------------------- /DOC/HTML/images/LDR-photo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joan2937/pigpio/c33738a320a3e28824af7807edafda440952c05d/DOC/HTML/images/LDR-photo.jpg -------------------------------------------------------------------------------- /DOC/HTML/images/LDR-wave-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joan2937/pigpio/c33738a320a3e28824af7807edafda440952c05d/DOC/HTML/images/LDR-wave-1.png -------------------------------------------------------------------------------- /DOC/HTML/images/LDR-wave-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joan2937/pigpio/c33738a320a3e28824af7807edafda440952c05d/DOC/HTML/images/LDR-wave-2.png -------------------------------------------------------------------------------- /DOC/HTML/images/LDR-wave-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joan2937/pigpio/c33738a320a3e28824af7807edafda440952c05d/DOC/HTML/images/LDR-wave-3.png -------------------------------------------------------------------------------- /DOC/HTML/images/breadboard.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joan2937/pigpio/c33738a320a3e28824af7807edafda440952c05d/DOC/HTML/images/breadboard.jpg -------------------------------------------------------------------------------- /DOC/HTML/images/caps.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joan2937/pigpio/c33738a320a3e28824af7807edafda440952c05d/DOC/HTML/images/caps.jpg -------------------------------------------------------------------------------- /DOC/HTML/images/driver.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joan2937/pigpio/c33738a320a3e28824af7807edafda440952c05d/DOC/HTML/images/driver.jpg -------------------------------------------------------------------------------- /DOC/HTML/images/faq-i2c-ss.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joan2937/pigpio/c33738a320a3e28824af7807edafda440952c05d/DOC/HTML/images/faq-i2c-ss.png -------------------------------------------------------------------------------- /DOC/HTML/images/faq-i2c.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joan2937/pigpio/c33738a320a3e28824af7807edafda440952c05d/DOC/HTML/images/faq-i2c.jpg -------------------------------------------------------------------------------- /DOC/HTML/images/faq-serial.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joan2937/pigpio/c33738a320a3e28824af7807edafda440952c05d/DOC/HTML/images/faq-serial.jpg -------------------------------------------------------------------------------- /DOC/HTML/images/faq-spi.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joan2937/pigpio/c33738a320a3e28824af7807edafda440952c05d/DOC/HTML/images/faq-spi.jpg -------------------------------------------------------------------------------- /DOC/HTML/images/faq1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joan2937/pigpio/c33738a320a3e28824af7807edafda440952c05d/DOC/HTML/images/faq1.jpg -------------------------------------------------------------------------------- /DOC/HTML/images/faq2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joan2937/pigpio/c33738a320a3e28824af7807edafda440952c05d/DOC/HTML/images/faq2.jpg -------------------------------------------------------------------------------- /DOC/HTML/images/faq3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joan2937/pigpio/c33738a320a3e28824af7807edafda440952c05d/DOC/HTML/images/faq3.jpg -------------------------------------------------------------------------------- /DOC/HTML/images/imu-1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joan2937/pigpio/c33738a320a3e28824af7807edafda440952c05d/DOC/HTML/images/imu-1.jpg -------------------------------------------------------------------------------- /DOC/HTML/images/imu-2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joan2937/pigpio/c33738a320a3e28824af7807edafda440952c05d/DOC/HTML/images/imu-2.jpg -------------------------------------------------------------------------------- /DOC/HTML/images/imu-3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joan2937/pigpio/c33738a320a3e28824af7807edafda440952c05d/DOC/HTML/images/imu-3.jpg -------------------------------------------------------------------------------- /DOC/HTML/images/ir-fritz.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joan2937/pigpio/c33738a320a3e28824af7807edafda440952c05d/DOC/HTML/images/ir-fritz.png -------------------------------------------------------------------------------- /DOC/HTML/images/ir-motion.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joan2937/pigpio/c33738a320a3e28824af7807edafda440952c05d/DOC/HTML/images/ir-motion.jpg -------------------------------------------------------------------------------- /DOC/HTML/images/ir-photo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joan2937/pigpio/c33738a320a3e28824af7807edafda440952c05d/DOC/HTML/images/ir-photo.jpg -------------------------------------------------------------------------------- /DOC/HTML/images/ir-rx.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joan2937/pigpio/c33738a320a3e28824af7807edafda440952c05d/DOC/HTML/images/ir-rx.jpg -------------------------------------------------------------------------------- /DOC/HTML/images/ir-wave-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joan2937/pigpio/c33738a320a3e28824af7807edafda440952c05d/DOC/HTML/images/ir-wave-1.png -------------------------------------------------------------------------------- /DOC/HTML/images/ir-wave-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joan2937/pigpio/c33738a320a3e28824af7807edafda440952c05d/DOC/HTML/images/ir-wave-2.png -------------------------------------------------------------------------------- /DOC/HTML/images/ir-wave-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joan2937/pigpio/c33738a320a3e28824af7807edafda440952c05d/DOC/HTML/images/ir-wave-3.png -------------------------------------------------------------------------------- /DOC/HTML/images/keypad.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joan2937/pigpio/c33738a320a3e28824af7807edafda440952c05d/DOC/HTML/images/keypad.jpg -------------------------------------------------------------------------------- /DOC/HTML/images/lcd.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joan2937/pigpio/c33738a320a3e28824af7807edafda440952c05d/DOC/HTML/images/lcd.jpg -------------------------------------------------------------------------------- /DOC/HTML/images/ldr-cap.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joan2937/pigpio/c33738a320a3e28824af7807edafda440952c05d/DOC/HTML/images/ldr-cap.jpg -------------------------------------------------------------------------------- /DOC/HTML/images/ldr.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joan2937/pigpio/c33738a320a3e28824af7807edafda440952c05d/DOC/HTML/images/ldr.jpg -------------------------------------------------------------------------------- /DOC/HTML/images/leds.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joan2937/pigpio/c33738a320a3e28824af7807edafda440952c05d/DOC/HTML/images/leds.jpg -------------------------------------------------------------------------------- /DOC/HTML/images/meter.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joan2937/pigpio/c33738a320a3e28824af7807edafda440952c05d/DOC/HTML/images/meter.jpg -------------------------------------------------------------------------------- /DOC/HTML/images/motor.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joan2937/pigpio/c33738a320a3e28824af7807edafda440952c05d/DOC/HTML/images/motor.jpg -------------------------------------------------------------------------------- /DOC/HTML/images/msp430.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joan2937/pigpio/c33738a320a3e28824af7807edafda440952c05d/DOC/HTML/images/msp430.jpg -------------------------------------------------------------------------------- /DOC/HTML/images/nano.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joan2937/pigpio/c33738a320a3e28824af7807edafda440952c05d/DOC/HTML/images/nano.jpg -------------------------------------------------------------------------------- /DOC/HTML/images/oled-2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joan2937/pigpio/c33738a320a3e28824af7807edafda440952c05d/DOC/HTML/images/oled-2.jpg -------------------------------------------------------------------------------- /DOC/HTML/images/oled.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joan2937/pigpio/c33738a320a3e28824af7807edafda440952c05d/DOC/HTML/images/oled.jpg -------------------------------------------------------------------------------- /DOC/HTML/images/pigpio-logo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joan2937/pigpio/c33738a320a3e28824af7807edafda440952c05d/DOC/HTML/images/pigpio-logo.gif -------------------------------------------------------------------------------- /DOC/HTML/images/pins.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joan2937/pigpio/c33738a320a3e28824af7807edafda440952c05d/DOC/HTML/images/pins.jpg -------------------------------------------------------------------------------- /DOC/HTML/images/pisc-1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joan2937/pigpio/c33738a320a3e28824af7807edafda440952c05d/DOC/HTML/images/pisc-1.jpg -------------------------------------------------------------------------------- /DOC/HTML/images/pisc-2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joan2937/pigpio/c33738a320a3e28824af7807edafda440952c05d/DOC/HTML/images/pisc-2.jpg -------------------------------------------------------------------------------- /DOC/HTML/images/pisc-3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joan2937/pigpio/c33738a320a3e28824af7807edafda440952c05d/DOC/HTML/images/pisc-3.jpg -------------------------------------------------------------------------------- /DOC/HTML/images/pot.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joan2937/pigpio/c33738a320a3e28824af7807edafda440952c05d/DOC/HTML/images/pot.jpg -------------------------------------------------------------------------------- /DOC/HTML/images/pro-mini.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joan2937/pigpio/c33738a320a3e28824af7807edafda440952c05d/DOC/HTML/images/pro-mini.jpg -------------------------------------------------------------------------------- /DOC/HTML/images/psu.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joan2937/pigpio/c33738a320a3e28824af7807edafda440952c05d/DOC/HTML/images/psu.jpg -------------------------------------------------------------------------------- /DOC/HTML/images/re-fritz.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joan2937/pigpio/c33738a320a3e28824af7807edafda440952c05d/DOC/HTML/images/re-fritz.png -------------------------------------------------------------------------------- /DOC/HTML/images/re-photo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joan2937/pigpio/c33738a320a3e28824af7807edafda440952c05d/DOC/HTML/images/re-photo.jpg -------------------------------------------------------------------------------- /DOC/HTML/images/re-wave-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joan2937/pigpio/c33738a320a3e28824af7807edafda440952c05d/DOC/HTML/images/re-wave-1.png -------------------------------------------------------------------------------- /DOC/HTML/images/re-wave-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joan2937/pigpio/c33738a320a3e28824af7807edafda440952c05d/DOC/HTML/images/re-wave-2.png -------------------------------------------------------------------------------- /DOC/HTML/images/remote-1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joan2937/pigpio/c33738a320a3e28824af7807edafda440952c05d/DOC/HTML/images/remote-1.jpg -------------------------------------------------------------------------------- /DOC/HTML/images/remote-2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joan2937/pigpio/c33738a320a3e28824af7807edafda440952c05d/DOC/HTML/images/remote-2.jpg -------------------------------------------------------------------------------- /DOC/HTML/images/reverse.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joan2937/pigpio/c33738a320a3e28824af7807edafda440952c05d/DOC/HTML/images/reverse.jpg -------------------------------------------------------------------------------- /DOC/HTML/images/rf-rx-2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joan2937/pigpio/c33738a320a3e28824af7807edafda440952c05d/DOC/HTML/images/rf-rx-2.jpg -------------------------------------------------------------------------------- /DOC/HTML/images/rf-rx.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joan2937/pigpio/c33738a320a3e28824af7807edafda440952c05d/DOC/HTML/images/rf-rx.jpg -------------------------------------------------------------------------------- /DOC/HTML/images/rf-tx.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joan2937/pigpio/c33738a320a3e28824af7807edafda440952c05d/DOC/HTML/images/rf-tx.jpg -------------------------------------------------------------------------------- /DOC/HTML/images/rotary.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joan2937/pigpio/c33738a320a3e28824af7807edafda440952c05d/DOC/HTML/images/rotary.jpg -------------------------------------------------------------------------------- /DOC/HTML/images/rpi.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joan2937/pigpio/c33738a320a3e28824af7807edafda440952c05d/DOC/HTML/images/rpi.jpg -------------------------------------------------------------------------------- /DOC/HTML/images/serial.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joan2937/pigpio/c33738a320a3e28824af7807edafda440952c05d/DOC/HTML/images/serial.jpg -------------------------------------------------------------------------------- /DOC/HTML/images/servo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joan2937/pigpio/c33738a320a3e28824af7807edafda440952c05d/DOC/HTML/images/servo.jpg -------------------------------------------------------------------------------- /DOC/HTML/images/sidebar.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joan2937/pigpio/c33738a320a3e28824af7807edafda440952c05d/DOC/HTML/images/sidebar.gif -------------------------------------------------------------------------------- /DOC/HTML/images/son-fritz.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joan2937/pigpio/c33738a320a3e28824af7807edafda440952c05d/DOC/HTML/images/son-fritz.png -------------------------------------------------------------------------------- /DOC/HTML/images/son-gnup-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joan2937/pigpio/c33738a320a3e28824af7807edafda440952c05d/DOC/HTML/images/son-gnup-1.png -------------------------------------------------------------------------------- /DOC/HTML/images/son-gnup-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joan2937/pigpio/c33738a320a3e28824af7807edafda440952c05d/DOC/HTML/images/son-gnup-2.png -------------------------------------------------------------------------------- /DOC/HTML/images/son-photo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joan2937/pigpio/c33738a320a3e28824af7807edafda440952c05d/DOC/HTML/images/son-photo.jpg -------------------------------------------------------------------------------- /DOC/HTML/images/son-wave-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joan2937/pigpio/c33738a320a3e28824af7807edafda440952c05d/DOC/HTML/images/son-wave-1.png -------------------------------------------------------------------------------- /DOC/HTML/images/son-wave-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joan2937/pigpio/c33738a320a3e28824af7807edafda440952c05d/DOC/HTML/images/son-wave-2.png -------------------------------------------------------------------------------- /DOC/HTML/images/son-wave-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joan2937/pigpio/c33738a320a3e28824af7807edafda440952c05d/DOC/HTML/images/son-wave-3.png -------------------------------------------------------------------------------- /DOC/HTML/images/son-wave-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joan2937/pigpio/c33738a320a3e28824af7807edafda440952c05d/DOC/HTML/images/son-wave-4.png -------------------------------------------------------------------------------- /DOC/HTML/images/speaker.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joan2937/pigpio/c33738a320a3e28824af7807edafda440952c05d/DOC/HTML/images/speaker.jpg -------------------------------------------------------------------------------- /DOC/HTML/images/spi-lnx-pi3b.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joan2937/pigpio/c33738a320a3e28824af7807edafda440952c05d/DOC/HTML/images/spi-lnx-pi3b.png -------------------------------------------------------------------------------- /DOC/HTML/images/spi-lnx-pibr1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joan2937/pigpio/c33738a320a3e28824af7807edafda440952c05d/DOC/HTML/images/spi-lnx-pibr1.png -------------------------------------------------------------------------------- /DOC/HTML/images/spi-pig-pi3b.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joan2937/pigpio/c33738a320a3e28824af7807edafda440952c05d/DOC/HTML/images/spi-pig-pi3b.png -------------------------------------------------------------------------------- /DOC/HTML/images/spi-pig-pibr1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joan2937/pigpio/c33738a320a3e28824af7807edafda440952c05d/DOC/HTML/images/spi-pig-pibr1.png -------------------------------------------------------------------------------- /DOC/HTML/images/srf02.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joan2937/pigpio/c33738a320a3e28824af7807edafda440952c05d/DOC/HTML/images/srf02.jpg -------------------------------------------------------------------------------- /DOC/HTML/images/srf04.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joan2937/pigpio/c33738a320a3e28824af7807edafda440952c05d/DOC/HTML/images/srf04.jpg -------------------------------------------------------------------------------- /DOC/HTML/images/stepper.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joan2937/pigpio/c33738a320a3e28824af7807edafda440952c05d/DOC/HTML/images/stepper.jpg -------------------------------------------------------------------------------- /DOC/HTML/images/switches.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joan2937/pigpio/c33738a320a3e28824af7807edafda440952c05d/DOC/HTML/images/switches.jpg -------------------------------------------------------------------------------- /DOC/HTML/images/topbar.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joan2937/pigpio/c33738a320a3e28824af7807edafda440952c05d/DOC/HTML/images/topbar.gif -------------------------------------------------------------------------------- /DOC/HTML/images/transistors.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joan2937/pigpio/c33738a320a3e28824af7807edafda440952c05d/DOC/HTML/images/transistors.jpg -------------------------------------------------------------------------------- /DOC/HTML/images/ubec-2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joan2937/pigpio/c33738a320a3e28824af7807edafda440952c05d/DOC/HTML/images/ubec-2.jpg -------------------------------------------------------------------------------- /DOC/HTML/images/uln2003a.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joan2937/pigpio/c33738a320a3e28824af7807edafda440952c05d/DOC/HTML/images/uln2003a.jpg -------------------------------------------------------------------------------- /DOC/HTML/images/wheel.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joan2937/pigpio/c33738a320a3e28824af7807edafda440952c05d/DOC/HTML/images/wheel.jpg -------------------------------------------------------------------------------- /DOC/HTML/images/wires.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joan2937/pigpio/c33738a320a3e28824af7807edafda440952c05d/DOC/HTML/images/wires.jpg -------------------------------------------------------------------------------- /DOC/HTML/images/yl-40.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joan2937/pigpio/c33738a320a3e28824af7807edafda440952c05d/DOC/HTML/images/yl-40.jpg -------------------------------------------------------------------------------- /DOC/HTML/scripts/index.css: -------------------------------------------------------------------------------- 1 | body 2 | { 3 | font-size: 100%; 4 | font-family: Arial, Helvetica, sans-serif; 5 | color: #101010; 6 | margin-left: 1%; margin-right: 10%; 7 | } 8 | 9 | h1 {font-size: 2.4em; color: #5d9dce; font-weight: bold;} 10 | h2 {font-size: 1.8em; color: #5d9dce; font-weight: bold;} 11 | h3 {font-size: 1.4em; color: #5d9dce; font-weight: bold;} 12 | h4 {font-size: 1.2em; color: #5d9dce;} 13 | h5 {font-size: 1.0em; color: #5d9dce;} 14 | h6 {font-size: 0.8em; color: #5d9dce;} 15 | 16 | code {display:block;font-size:80%; font-family: "Courier New", Courier, monospace; background-color:#D0D0D0;} 17 | pre {font-size:80%; font-family: Courier; background-color:#D0D020;} 18 | 19 | table.ev 20 | { 21 | border: 3px solid green; 22 | } 23 | 24 | td.ev1 25 | { 26 | width: 200px; 27 | border: 1px solid green; 28 | } 29 | 30 | td.ev2 31 | { 32 | border: 1px solid green; 33 | } 34 | 35 | a.l1:link,a.l1:visited 36 | { 37 | display:block; 38 | font-weight:bold; 39 | color:#FFFFFF; 40 | background-color:#98bf21; 41 | width:120px; 42 | text-align:center; 43 | padding:4px; 44 | text-decoration:none; 45 | } 46 | 47 | a.l1:hover,a.l1:active 48 | { 49 | background-color:#7A991A; 50 | } 51 | 52 | 53 | -------------------------------------------------------------------------------- /DOC/HTML/scripts/standard.css: -------------------------------------------------------------------------------- 1 | html { height: 100% } 2 | body { height: 100%; margin: 0px; padding: 0px } 3 | #map_canvas { height: 100% } 4 | -------------------------------------------------------------------------------- /DOC/MAN/README: -------------------------------------------------------------------------------- 1 | Placeholder directory for man pages. 2 | -------------------------------------------------------------------------------- /DOC/README: -------------------------------------------------------------------------------- 1 | bin various scripts to generate man pages and HTML 2 | 3 | dbase defines the structure of the web documentation 4 | 5 | HTML auto generated html web site 6 | 7 | makedoc run to regenerate documentation 8 | 9 | MAN auto generated man pages 10 | 11 | src/defs edit to change pigs, pigpiod, pig2vcd, and examples docs 12 | 13 | src/html edit to change the fairly invariant web pages 14 | DO NOT ADD auto generated HTML to this directory 15 | 16 | tmp stores temporary files, may be deleted 17 | -------------------------------------------------------------------------------- /DOC/bin/backup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # backup database 4 | cp dbase/pigpio.sqlite dbase/pigpio.sqlite.bak 5 | 6 | -------------------------------------------------------------------------------- /DOC/bin/body.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import glob 4 | 5 | for fn in glob.glob("src/html/*.html"): 6 | f = open(fn) 7 | h = f.read() 8 | f.close() 9 | s1,d1,e1=h.partition("") 10 | s2,d2,e2=e1.partition("") 11 | f = open("tmp/body/" + fn[9:-5] + ".body", "w") 12 | f.write(s2) 13 | f.close() 14 | 15 | -------------------------------------------------------------------------------- /DOC/bin/build_site.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import os 4 | import sqlite3 5 | 6 | db=sqlite3.connect("dbase/pigpio.sqlite") 7 | 8 | c=db.cursor() 9 | 10 | c.execute("select file_name from pigpio") 11 | 12 | names = c.fetchall() 13 | 14 | for n in names: 15 | os.system("bin/html.py {0} >HTML/{0}.html".format(n[0])) 16 | print(n[0]) 17 | 18 | c.close() 19 | 20 | db.close() 21 | 22 | -------------------------------------------------------------------------------- /DOC/bin/examples.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | from collections import OrderedDict 5 | 6 | def emit(s): 7 | sys.stdout.write(s) 8 | 9 | def get_line(f): 10 | line = f.readline() 11 | return line 12 | 13 | def get_file(): 14 | try: 15 | fn = sys.argv[1] 16 | f = open(fn, "r") 17 | except: 18 | exit("aborting, can't open {}".format(fn)) 19 | return f 20 | 21 | def cancel_row(): 22 | global in_row 23 | if in_row: 24 | in_row = False 25 | emit('') 26 | 27 | def start_row(): 28 | global in_row 29 | if not in_row: 30 | in_row = True 31 | emit('') 32 | 33 | def cancel_table(): 34 | global in_table 35 | if in_table: 36 | in_table = False 37 | cancel_row() 38 | emit('') 39 | 40 | def start_table(): 41 | global in_table 42 | if not in_table: 43 | in_table = True 44 | emit('') 45 | else: 46 | cancel_row() 47 | start_row() 48 | 49 | index = {} 50 | 51 | in_code = False 52 | in_samp = False 53 | in_table = False 54 | in_row = False 55 | 56 | f = get_file() 57 | 58 | while True: 59 | 60 | line = get_line(f) 61 | 62 | if line == "": 63 | cancel_table() 64 | 65 | emit('
\n') 66 | last = None 67 | ordered = OrderedDict(sorted(index.items(), key=lambda t: t[1].lower())) 68 | for k,v in ordered.items(): 69 | tag=k.split('_')[0] 70 | if last != v.lower(): 71 | if last is not None: 72 | emit('') 73 | last = v.lower() 74 | anchor="index_"+last.replace(" ", "_") 75 | emit('
'+v+'') 76 | emit(' '+tag+'\n') 77 | emit('
') 78 | break 79 | 80 | if line.startswith("?0|"): 81 | s = line.split("|") 82 | anchor=s[1].strip() 83 | emit(''+anchor+'
') 84 | continue 85 | 86 | if line.startswith("?1|"): 87 | cancel_table() 88 | s = line.split("|") 89 | tag = s[1].strip()+"_" 90 | anchor=s[2].strip() 91 | emit('

'+anchor+'

') 92 | continue 93 | 94 | elif line.startswith("?2|") or line.startswith("?3|") or line.startswith("?4|"): 95 | start_table() 96 | 97 | s = line.split("|") 98 | 99 | anchor=tag+s[1].strip() 100 | 101 | if line.startswith("?2|"): 102 | link=s[1].strip()+".html" 103 | elif line.startswith("?3|"): 104 | link="code/"+s[1].strip()+".zip" 105 | elif line.startswith("?4|"): 106 | link=s[1].strip() 107 | else: 108 | link="code/"+s[1].strip() 109 | 110 | date=s[2].strip() 111 | 112 | title=s[3].strip() 113 | emit(''+title+'
'+date+'
') 114 | 115 | index.update({anchor:title}) 116 | 117 | continue 118 | 119 | else: 120 | emit(line.replace("\n", "
\n")) 121 | 122 | f.close() 123 | 124 | -------------------------------------------------------------------------------- /DOC/bin/html.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | import sqlite3 5 | import time 6 | 7 | i_file_name = 0 8 | i_menu_title = 1 9 | i_menu_pos = 2 10 | i_menu_level = 3 11 | i_page_title = 4 12 | i_pic1 = 5 13 | i_pic2 = 6 14 | i_pic3 = 7 15 | i_body = 8 16 | 17 | print(""" 18 | 20 | 21 | 22 | 23 | 24 | 25 | pigpio library 26 | 27 | 28 | 29 | 30 | 31 | """) 32 | 33 | page = sys.argv[1] 34 | 35 | menuH = "" 36 | menuV = "" 37 | sitemap = "" 38 | 39 | header = 'pigpio library' 40 | 41 | footer1 = "© 2012-2020"; 42 | footer2 = "e-mail: pigpio @ abyz.me.uk"; 43 | footer3 = "Updated: " + time.strftime("%d/%m/%Y") + ""; 44 | 45 | db=sqlite3.connect("dbase/pigpio.sqlite") 46 | 47 | c=db.cursor() 48 | 49 | def menu_titles(): 50 | 51 | global menuV, menuH 52 | 53 | c.execute( 54 | "SELECT file_name, menu_title, menu_level FROM pigpio ORDER by menu_pos") 55 | 56 | recs = c.fetchall() 57 | 58 | menuV = "" 59 | menuH = "" 60 | 61 | for r in recs: 62 | if r[2] == 1: 63 | menuV += '' + r[1] + '\n' 64 | menuH += '[' + r[1] + ']\n' 65 | 66 | def sitemap(): 67 | 68 | c.execute( 69 | "SELECT file_name, menu_title, menu_level FROM pigpio ORDER by menu_pos") 70 | 71 | recs = c.fetchall() 72 | 73 | stemap = "" 74 | 75 | for r in recs: 76 | if r[2] > 0: 77 | s = "----" * (r[2]-1) 78 | stemap += s + '' + r[1] + '
\n' 79 | 80 | return stemap 81 | 82 | def check_image(d): 83 | 84 | img = "images/" + d 85 | 86 | try: 87 | with open("HTML/" + img) as f: 88 | print('') 89 | except: 90 | pass 91 | 92 | titles = menu_titles() 93 | 94 | s_sidebar = 'style="background:#EAF2E6 url(\'images/sidebar.gif\') repeat-y; width:35px; height:100%"' 95 | 96 | s_header = 'style="background:url(\'images/topbar.gif\') repeat-x; height: 70px; font-size:1.5em; vertical-align: top;"' 97 | 98 | s_menuV = 'style="vertical-align: top; background-color: #98bf21;"' 99 | 100 | c.execute("SELECT * FROM pigpio WHERE file_name=?", (page,)) 101 | 102 | rec = c.fetchone() 103 | 104 | if page == "sitemap": 105 | body = sitemap() 106 | else: 107 | body = rec[i_body] 108 | 109 | c.close() 110 | db.close() 111 | 112 | print('') 113 | print('') 114 | print('') 134 | print('
') 115 | print('') 116 | print('
' + header + '
') 117 | print('
') 118 | print('
') 119 | check_image(rec[i_pic1]) 120 | check_image(rec[i_pic2]) 121 | check_image(rec[i_pic3]) 122 | print('
') 123 | print("") 124 | print('') 125 | print('') 126 | print('
' + menuV + '

' + rec[i_page_title] + '

' + body + '
') 127 | print('
' + menuH + '
') 128 | print('') 129 | print('') 130 | print('') 131 | print('') 132 | print('
' + footer1 + '
' + footer2 + '
' + footer3 + '
') 133 | print('
') 135 | 136 | print('\n') 137 | 138 | -------------------------------------------------------------------------------- /DOC/bin/purge.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # if backup same as new delete it 4 | if cmp -s dbase/pigpio.sqlite dbase/pigpio.sqlite.bak 5 | then 6 | rm dbase/pigpio.sqlite.bak 7 | else 8 | d=$(date "+%F-%H-%M-%S") 9 | mv -f dbase/pigpio.sqlite.bak dbase/pigpio.sqlite.$d 10 | fi 11 | 12 | # delete backups older than a week 13 | find dbase/pigpio.sqlite.2* -mtime +7 -delete &>/dev/null 14 | 15 | -------------------------------------------------------------------------------- /DOC/bin/tidy.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import glob 4 | 5 | def snafu(t, s, r): 6 | l = t 7 | while l.find(s) != -1: 8 | l = l.replace(s, r) 9 | return l 10 | 11 | for n in glob.glob("tmp/body/*.body"): 12 | 13 | f = open(n, "r"); 14 | t = f.read() 15 | f.close() 16 | 17 | t = snafu(t, "

", "

") 18 | t = snafu(t, "

", "

") 19 | t = snafu(t, "


", "") 20 | t = snafu(t, "\n
", "\n") 21 | t = snafu(t, "
", "") 22 | t = snafu(t, "\n
", "\n") 23 | t = snafu(t, "


", "

") 24 | 25 | f = open(n, "w"); 26 | f.write(t) 27 | f.close() 28 | 29 | -------------------------------------------------------------------------------- /DOC/bin/updatesql.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sqlite3 4 | import glob 5 | 6 | db=sqlite3.connect("dbase/pigpio.sqlite") 7 | 8 | c=db.cursor() 9 | 10 | for fn in glob.glob("tmp/body/*.body"): 11 | f = open(fn, encoding='utf-8') 12 | body = f.read() 13 | f.close() 14 | c.execute("UPDATE pigpio SET body=? WHERE file_name=?", (body, fn[9:-5])) 15 | 16 | c.close() 17 | 18 | db.commit() 19 | 20 | db.close() 21 | 22 | -------------------------------------------------------------------------------- /DOC/dbase/pigpio.sqlite: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joan2937/pigpio/c33738a320a3e28824af7807edafda440952c05d/DOC/dbase/pigpio.sqlite -------------------------------------------------------------------------------- /DOC/makedoc: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | mkdir -p tmp/pydoc 4 | mkdir -p tmp/body 5 | 6 | echo "*** making man pages ***" 7 | 8 | echo "pigs" 9 | bin/smakdoc.py src/defs/pigs.def man >MAN/pigs.1 10 | 11 | echo "pigpiod" 12 | bin/cmakdoc.py pigpiod src/defs/pigpiod.def man >MAN/pigpiod.1 13 | 14 | echo "pig2vcd" 15 | bin/cmakdoc.py pig2vcd src/defs/pig2vcd.def man >MAN/pig2vcd.1 16 | 17 | echo "pigpio.h" 18 | bin/cmakdoc.py pigpio ../pigpio.h man >MAN/pigpio.3 19 | 20 | echo "pigpiod_if.h" 21 | bin/cmakdoc.py pigpiod_if ../pigpiod_if.h man >MAN/pigpiod_if.3 22 | 23 | echo "pigpiod_if2.h" 24 | bin/cmakdoc.py pigpiod_if2 ../pigpiod_if2.h man >MAN/pigpiod_if2.3 25 | 26 | # *** preparing HTML bodies *** 27 | 28 | bin/smakdoc.py src/defs/pigs.def >tmp/body/pigs.body 29 | bin/cmakdoc.py pigpiod src/defs/pigpiod.def >tmp/body/pigpiod.body 30 | bin/cmakdoc.py pig2vcd src/defs/pig2vcd.def >tmp/body/pig2vcd.body 31 | bin/cmakdoc.py pigpio ../pigpio.h >tmp/body/cif.body 32 | bin/cmakdoc.py pigpiod_if ../pigpiod_if.h >tmp/body/pdif.body 33 | bin/cmakdoc.py pigpiod_if2 ../pigpiod_if2.h >tmp/body/pdif2.body 34 | pydoc ../pigpio.py >tmp/pydoc/pigpio.pydoc 35 | bin/pymakdoc.py tmp/pydoc/pigpio.pydoc >tmp/body/python.body 36 | bin/examples.py src/defs/examples.def >tmp/body/examples.body 37 | 38 | bin/body.py # get bodies of manually generated pages 39 | bin/tidy.py # tidy the bodies 40 | bin/backup.sh # backup database 41 | bin/updatesql.py # update the database with the new bodies 42 | bin/purge.sh # remove redundant datatbase copies 43 | 44 | echo "*** making web pages ***" 45 | 46 | bin/build_site.py # construct the web site 47 | 48 | -------------------------------------------------------------------------------- /DOC/src/defs/pig2vcd.def: -------------------------------------------------------------------------------- 1 | 2 | /*TEXT 3 | pig2vcd is a utility which reads notifications on stdin and writes the 4 | output as a Value Change Dump (VCD) file on stdout. 5 | 6 | The VCD file can be viewed using GTKWave. 7 | 8 | *Notifications* 9 | 10 | Notifications consist of 12 bytes with the following binary format. 11 | 12 | . . 13 | typedef struct 14 | { 15 | uint16_t seqno; 16 | uint16_t flags; 17 | uint32_t tick; 18 | uint32_t level; 19 | } gpioReport_t; 20 | . . 21 | 22 | seqno: starts at 0 each time the handle is opened and then increments by one for each report. 23 | 24 | flags: two flags are defined, PI_NTFY_FLAGS_WDOG and PI_NTFY_FLAGS_ALIVE. If bit 5 is set (PI_NTFY_FLAGS_WDOG) then bits 0-4 of the flags indicate a gpio which has had a watchdog timeout; if bit 6 is set (PI_NTFY_FLAGS_ALIVE) this indicates a keep alive signal on the pipe/socket and is sent once a minute in the absence of other notification activity. 25 | 26 | tick: the number of microseconds since system boot. It wraps around after 1h12m. 27 | 28 | level: indicates the level of each gpio. If bit 1< 2 | 3 | 4 | 5 | 6 | download 7 | 8 | 9 | If the pigpio daemon is running it should be killed (sudo killall 10 | pigpiod) before make install and restarted afterwards (sudo 11 | pigpiod).
12 |
13 | The initial part of the make, the 14 | compilation of pigpio.c, takes 100 seconds on early model 15 | Pis.  Be patient.  The overall install takes just over 3 16 | minutes.
17 |

Download and install latest version

18 | 19 | wget https://github.com/joan2937/pigpio/archive/master.zip
20 | unzip master.zip
21 | cd pigpio-master
22 | make
23 | sudo make install
24 |
25 |
26 | If the Python part of the install fails it may be because you need 27 | the setup tools.
28 |
29 | sudo apt install python-setuptools 30 | python3-setuptools

31 |
32 |

To check the library

33 | These tests make extensive use of GPIO 25 (pin 22).  Make sure 34 | nothing, or only a LED, is connected to the GPIO before running the 35 | tests.  Most tests are statistical in nature and so may on 36 | occasion fail.  Repeated failures on the same test or many 37 | failures in a group of tests indicate a problem.
38 |
39 | sudo ./x_pigpio # check C I/F
40 |
41 | sudo pigpiod    # start daemon
42 |
43 | ./x_pigpiod_if2 # check C      I/F to 44 | daemon
45 | ./x_pigpio.py   # check Python I/F to daemon
46 | ./x_pigs        # check 47 | pigs   I/F to daemon
48 | ./x_pipe        # check 49 | pipe   I/F to daemon
50 |
51 |
52 |

To compile, link, and run a C program

53 | gcc -Wall -pthread -o foobar foobar.c -lpigpio -lrt
54 | sudo ./foobar


55 |

To start the pigpio daemon

56 | sudo pigpiod
57 |

To stop the pigpio daemon

58 | sudo killall pigpiod

59 |

github

60 | git clone https://github.com/joan2937/pigpio
61 |

Raspbian (raspberrypi.org image)

62 |

This may not be the most recent version.  You can check the 63 | version with the command pigpiod -v.

64 | sudo apt-get update
65 | sudo apt-get install pigpio python-pigpio python3-pigpio

66 |
67 | 68 | 69 | -------------------------------------------------------------------------------- /DOC/src/html/ex_LDR.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | LDR example 7 | 8 | 9 |

The following code shows a method of reading analogue sensors on 10 | the digital input only Pi.  A Light Dependent Resistor (LDR) 11 | varies its resistance according to the incident light 12 | intensisty.

13 |

SETUP

14 | fritzing diagramThe LDR 16 | used is a Cadmium Sulphide device with a 1MOhm dark resistance and 17 | 2-4KOhm at 100 lux.  The capacitor is a 104 18 | ceramic.
19 |
20 | One end of the capacitor is connected to Pi ground.
21 |
22 | One end of the LDR is connected to Pi 3V3.
23 |
24 | The other ends of the capacitor and LDR are connected to a spare 25 | gpio.

26 |

Here P1-1 is used for 3V3, P1-20 is used for ground, and gpio 18 27 | (P1-12) is used for the gpio.

28 |

photo of set-up

30 |

CODE

31 | #include <stdio.h>
32 |
33 | #include <pigpio.h>
34 |
35 | /* 36 | -----------------------------------------------------------------------
37 | 38 |
39 |    3V3 ----- Light Dependent Resistor --+-- Capacitor 40 | ----- Ground
41 |                                         42 | |
43 |                                         44 | +-- gpio
45 |
46 |
47 |   cc -o LDR LDR.c -lpigpio -lpthread -lrt
48 |   sudo ./LDR
49 |
50 | */
51 |
52 | #define LDR 18
53 |
54 | /* forward declaration */
55 |
56 | void alert(int pin, int level, uint32_t tick);
57 |
58 | int main (int argc, char *argv[])
59 | {
60 |    if (gpioInitialise()<0) return 1;
61 |
62 |    gpioSetAlertFunc(LDR, alert); /* call alert when LDR 63 | changes state */
64 |     
65 |    while (1)
66 |    {
67 |       gpioSetMode(LDR, PI_OUTPUT); /* 68 | drain capacitor */
69 |
70 |       gpioWrite(LDR, PI_OFF);
71 |
72 |       gpioDelay(200); /* 50 micros is 73 | enough, 200 is overkill */
74 |
75 |       gpioSetMode(LDR, PI_INPUT); /* start 76 | capacitor recharge */
77 |
78 |       gpioDelay(10000); /* nominal 100 79 | readings per second */
80 |    }
81 |
82 |    gpioTerminate();
83 | }
84 |
85 | void alert(int pin, int level, uint32_t tick)
86 | {
87 |    static uint32_t inited = 0;
88 |    static uint32_t lastTick, firstTick;
89 |
90 |    uint32_t diffTick;
91 |
92 |    if (inited)
93 |    {
94 |       diffTick = tick - lastTick;
95 |       lastTick = tick;
96 |
97 |       if (level == 1) printf("%u %d\ ", 98 | tick-firstTick, diffTick);
99 |    }
100 |    else
101 |    {
102 |       inited = 1;
103 |       firstTick = tick;
104 |       lastTick = firstTick;
105 |    }
106 | }
107 |

BUILD

108 | cc -o LDR LDR.c -lpigpio -lrt -lpthread
109 |

RUN

110 | sudo ./LDR >LDR.dat &
111 |
112 | While the program is running you can capture the waveform using the 113 | notification feature built in to pigpio.  Issue the following 114 | commands on the Pi.
115 |
116 | pigs no
117 | pig2vcd  </dev/pigpio0 >LDR.vcd &
118 | pigs nb 0 0x40000 # set bit for gpio 18
119 |

Change the light falling on the LDR for a few seconds (e.g. 120 | shine a torch on it or shade it with your hands).

121 | pigs nc 0
122 |

The file LDR.vcd will contain the captured waveform, which can 123 | be viewed using GTKWave.

124 |

Overview

125 | LDR waveform 1
127 |

Reading circa every 10ms

128 | LDR waveform 2
130 |

One reading, circa 400us

131 | LDR waveform 3
133 |

The file LDR.dat will contain pairs of timestamps and recharge 134 | time (in us).  The following  script will convert the 135 | timestamps into seconds.

137 |

awk '{print $1/1000000, $2}' LDR.dat 138 | >LDR-secs.dat

139 |

Gnuplot is a useful tool to graph data.

140 | plot [14:24] 'LDR-secs.dat' with lines title 'LDR' 141 |

Gnuplot readings 14-24 seconds

142 |

gnuplot 1

144 | plot [18:21] 'LDR-secs.dat' with lines title 'LDR'
145 |
146 | Gnuplot readings 18-21 seconds 147 |

Gnuplot 2

149 | 150 | 151 | -------------------------------------------------------------------------------- /DOC/src/html/ex_rotary_encoder.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Rotary encoder sample 7 | 8 | 9 |

The following code shows one way to read an incremental 10 | mechanical rotary enoder (the sort used for volume control in audio 11 | systems).  These rotary encoders have two switches A and B 12 | which return a quadrature output, i.e. they are 90 degrees out of 13 | phase.

14 |

SETUP

15 | fritzing diagramThe common 17 | (centre) terminal should be connected to a Pi ground. 18 |

The A and B terminals may be connected to any spare gpios.

19 |

Here A to gpio18 (P1-12), common to ground (P1-20), B to gpio7 20 | (P1-26).

21 |

photo of set-up

23 |

CODE

24 | #include <stdio.h>
25 |
26 | #include <pigpio.h>
27 |
28 | /*
29 |    Rotary encoder connections:
30 |
31 |    Encoder A      - gpio 32 | 18   (pin P1-12)
33 |    Encoder B      - gpio 34 | 7    (pin P1-26)
35 |    Encoder Common - Pi ground (pin P1-20)
36 | */
37 |
38 | #define ENCODER_A 18
39 | #define ENCODER_B  7
40 |
41 | static volatile int encoderPos;
42 |
43 | /* forward declaration */
44 |
45 | void encoderPulse(int gpio, int lev, uint32_t tick);
46 |
47 | int main(int argc, char * argv[])
48 | {
49 |    int pos=0;
50 |
51 |    if (gpioInitialise()<0) return 1;
52 |
53 |    gpioSetMode(ENCODER_A, PI_INPUT);
54 |    gpioSetMode(ENCODER_B, PI_INPUT);
55 |
56 |    /* pull up is needed as encoder common is grounded 57 | */
58 |
59 |    gpioSetPullUpDown(ENCODER_A, PI_PUD_UP);
60 |    gpioSetPullUpDown(ENCODER_B, PI_PUD_UP);
61 |
62 |    encoderPos = pos;
63 |
64 |    /* monitor encoder level changes */
65 |
66 |    gpioSetAlertFunc(ENCODER_A, encoderPulse);
67 |    gpioSetAlertFunc(ENCODER_B, encoderPulse);
68 |
69 |    while (1)
70 |    {
71 |       if (pos != encoderPos)
72 |       {
73 |          pos = 74 | encoderPos;
75 |          printf("pos=%d\ ", 76 | pos);
77 |       }
78 |       gpioDelay(20000); /* check pos 50 79 | times per second */
80 |    }
81 |
82 |    gpioTerminate();
83 | }
84 |
85 | void encoderPulse(int gpio, int level, uint32_t tick)
86 | {
87 |    /*
88 |
89 |              90 | +---------+         91 | +---------+      0
92 |              93 | |         94 | |         95 | |         |
96 |    A         97 | |         98 | |         99 | |         |
100 |              101 | |         102 | |         103 | |         |
104 |    105 | +---------+         106 | +---------+         +----- 107 | 1
108 |
109 |        110 | +---------+         111 | +---------+            112 | 0
113 |        114 | |         115 | |         116 | |         |
117 |    B   118 | |         119 | |         120 | |         |
121 |        122 | |         123 | |         124 | |         |
125 |    ----+         126 | +---------+         127 | +---------+  1
128 |
129 |    */
130 |
131 |    static int levA=0, levB=0, lastGpio = -1;
132 |
133 |    if (gpio == ENCODER_A) levA = level; else levB = 134 | level;
135 |
136 |    if (gpio != lastGpio) /* debounce */
137 |    {
138 |       lastGpio = gpio;
139 |
140 |       if ((gpio == ENCODER_A) && 141 | (level == 0))
142 |       {
143 |          if (!levB) 144 | ++encoderPos;
145 |       }
146 |       else if ((gpio == ENCODER_B) 147 | && (level == 1))
148 |       {
149 |          if (levA) 150 | --encoderPos;
151 |       }
152 |    }
153 | }
154 |

BUILD

155 | cc -o rotary_encoder rotary_encoder.c -lpigpio -lrt 156 | -lpthread
157 |

RUN

158 | sudo ./rotary_encoder
159 |

While the program is running you can capture the waveform using 160 | the notification feature built in to pigpio.  Issue the 161 | following commands on the Pi.

162 | pigs no
163 | pig2vcd  </dev/pigpio0 >re.vcd &
164 | pigs nb 0 0x40080 # set bits for gpios 7 (0x80) and 18 165 | (0x40000)
166 |

Twiddle the rotary encoder forwards and backwards for a few 167 | seconds.  Then enter

168 | pigs nc 0
169 |

The file re.vcd will contain the captured waveform, which can be 170 | viewed using GTKWave.

171 |
172 | Overview
173 |
174 | 176
177 |
178 | Detail of switch bounce.  Contact A bounces for circa 700 us 179 | before completing the level transition
180 |
181 | 183
184 | 185 | 186 | -------------------------------------------------------------------------------- /DOC/src/html/ex_sonar_ranger.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Sonar ranger example 7 | 8 | 9 |

The following code shows a method of reading a class of sonar 10 | rangers.  These rangers requires a trigger pulse.  11 | Shortly after receiving a trigger they transmit a noise pulse and 12 | set the echo line high.  When the echo is received the echo 13 | line is set low.

14 |

SETUP

15 | fritzing diagram
17 |
18 |
19 |
20 |
21 | The ranger used is a SRF05 (check the pinouts, there are many 22 | variants).
23 |
24 | The fritzing diagram shows the back of the ranger, i.e. pin 1 is 25 | the rightmost.
26 |
27 | Pin 1 is 5V.
28 | Pin 2 is the trigger line.
29 | Pin 3 is the echo line.
30 | Pin 4 is out (unused).
31 | Pin 5 is ground.
32 |
33 |

photo of set-up

35 |

CODE

36 | #include <stdio.h>
37 |
38 | #include <pigpio.h>
39 |
40 | /*
41 |
42 | P1  Name  gpio    used for
43 |
44 |  2  5V    ---     45 | 5V
46 |  6  GND   ---     47 | Ground
48 | 24  CE0   8       49 | Sonar echo
50 | 26  CE1   7       51 | Sonar trigger
52 |
53 | */
54 |
55 | #define SONAR_TRIGGER 7
56 | #define SONAR_ECHO    8
57 |
58 | /* forward prototypes */
59 |
60 | void sonarTrigger(void);
61 |
62 | void sonarEcho(int gpio, int level, uint32_t tick);
63 |
64 | int main(int argc, char *argv[])
65 | {
66 |    if (gpioInitialise()<0) return 1;
67 |
68 |    gpioSetMode(SONAR_TRIGGER, PI_OUTPUT);
69 |    gpioWrite  (SONAR_TRIGGER, PI_OFF);
70 |
71 |    gpioSetMode(SONAR_ECHO,    72 | PI_INPUT);
73 |
74 |    /* update sonar 20 times a second, timer #0 */
75 |
76 |    gpioSetTimerFunc(0, 50, sonarTrigger); /* every 50ms 77 | */
78 |
79 |    /* monitor sonar echos */
80 |
81 |    gpioSetAlertFunc(SONAR_ECHO, sonarEcho);
82 |
83 |    while (1) sleep(1);
84 |
85 |    gpioTerminate();
86 |
87 |    return 0;
88 | }
89 |
90 | void sonarTrigger(void)
91 | {
92 |    /* trigger a sonar reading */
93 |
94 |    gpioWrite(SONAR_TRIGGER, PI_ON);
95 |
96 |    gpioDelay(10); /* 10us trigger pulse */
97 |
98 |    gpioWrite(SONAR_TRIGGER, PI_OFF);
99 | }
100 |
101 | void sonarEcho(int gpio, int level, uint32_t tick)
102 | {
103 |    static uint32_t startTick, firstTick=0;
104 |
105 |    int diffTick;
106 |
107 |    if (!firstTick) firstTick = tick;
108 |
109 |    if (level == PI_ON)
110 |    {
111 |       startTick = tick;
112 |    }
113 |    else if (level == PI_OFF)
114 |    {
115 |       diffTick = tick - startTick;
116 |
117 |       printf("%u %u\ ", tick-firstTick, 118 | diffTick);
119 |    }
120 | }
121 |

BUILD

122 | cc -o sonar sonar.c -lpigpio -lrt -lpthread
123 |

RUN

124 | sudo ./sonar >sonar.dat &
125 |
126 | While the program is running you can capture the waveform using the 127 | notification feature built in to pigpio.  Issue the following 128 | commands on the Pi.
129 |
130 | pigs no
131 | pig2vcd  </dev/pigpio0 >sonar.vcd &
132 | pigs nb 0 0x180 # set bits for gpios 7 and 8
133 |

Move an object in front of the sonar ranger for a few 134 | seconds.

135 | pigs nc 0
136 |

The file sonar.vcd will contain the captured waveform, which can 137 | be viewed using GTKWave.

138 |

Overview

139 | LDR waveform 1
141 |

Reading circa every 10ms

142 | Sonar waveform 2
144 |

One reading, circa 400us

145 | Sonar waveform 3
147 |

another

148 | Sonar waveform 4
150 |

The file sonar.dat will contain pairs of timestamps and echo 151 | length (in us).  The following  script will convert the 152 | timestamps into seconds.

154 |

awk '{print $1/1000000, $2}' sonar.dat 155 | >sonar-secs.dat

156 |

Gnuplot is a useful tool to graph data.

157 | plot 'sonar-secs.dat' title 'Sonar'
158 |

gnuplot 1
160 |  plot [10:25] 'sonar-secs.dat' title 'Sonar'

161 |

gnuplot 1

163 | 164 | 165 | -------------------------------------------------------------------------------- /DOC/src/html/misc.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Miscellaneous 7 | 8 | 9 | There are two C libraries which provide a socket interface to the 10 | pigpio daemon.  They provide an interface very similar to the 11 | pigpio Python module.
12 |
    13 |
  • The original pigpiod_if library is 14 | now deprecated and will no longer be updated.  This library is 15 | limited to controlling one Pi at a time.
  • 16 |
17 |
    18 |
  • The new pigpiod_if2 library which 19 | should be used for new code.  This library allows multiple Pis 20 | to be controlled at one time.
  • 21 |
22 | Additional details of the pigpio socket 23 | interface.
24 |
25 | Additional details of the pigpio pipe 26 | interface.
27 |
28 | pig2vcd is a utility which converts 29 | pigpio notifications into the VCD (Value Change Dump) format.  30 | VCD can be read by many programs, in particular GTKWave. 32 | 33 | 34 | -------------------------------------------------------------------------------- /DOC/src/html/pif.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Pipe interface 7 | 8 | 9 | pigpio provides a pipe interface to many of its functions.
10 |
11 | The pipe interface is available whenever pigpio is running, either 12 | because it has been started as a daemon, or it has been linked in 13 | to a running user program.  The pipe interface can be disabled 14 | by the program which initialises the library.  pigpiod offers 15 | the -f option to disable the pipe interface.  User programs 16 | should call gpioCfgInterfaces 18 | if they wish to disable the pipe interface.
19 |
20 | pigpio listens for commands on pipe /dev/pigpio.  The commands 21 | consist of a command identifier with, depending on the command, 22 | zero, one, or two parameters.  The result, if any, may be read 23 | from pipe /dev/pigout.  If any errors are detected a message 24 | will be written to pipe /dev/pigerr.
25 |
26 |
27 | The format of the commands is identical to those used by pigs. 29 | 30 | 31 | -------------------------------------------------------------------------------- /EXAMPLES/C/COUNTER_1/README: -------------------------------------------------------------------------------- 1 | A program showing how to use the gpioSetAlertFunc function to set a callback for gpio state changes. 2 | 3 | A frequency count is generated for each monitored gpio (frequencies up to 500KHz and beyond). 4 | -------------------------------------------------------------------------------- /EXAMPLES/C/COUNTER_1/freq_count_1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include 7 | 8 | /* 9 | 2014-08-20 10 | 11 | gcc -o freq_count_1 freq_count_1.c -lpigpio -lpthread 12 | $ sudo ./freq_count_1 4 7 8 13 | 14 | This program uses the gpioSetAlertFunc function to request 15 | a callback (the same one) for each gpio to be monitored. 16 | 17 | EXAMPLES 18 | 19 | Monitor gpio 4 (default settings) 20 | sudo ./freq_count_1 4 21 | 22 | Monitor gpios 4 and 8 (default settings) 23 | sudo ./freq_count_1 4 8 24 | 25 | Monitor gpios 4 and 8, sample rate 2 microseconds 26 | sudo ./freq_count_1 4 8 -s2 27 | 28 | Monitor gpios 7 and 8, sample rate 4 microseconds, report every second 29 | sudo ./freq_count_1 7 8 -s4 -r10 30 | 31 | Monitor gpios 4,7, 8, 9, 10, 23 24, report five times a second 32 | sudo ./freq_count_1 4 7 8 9 10 23 24 -r2 33 | 34 | Monitor gpios 4, 7, 8, and 9, report once a second, sample rate 1us, 35 | generate 2us edges (4us square wave, 250000 highs per second). 36 | sudo ./freq_count_1 4 7 8 9 -r 10 -s 1 -p 2 37 | */ 38 | 39 | #define MAX_GPIOS 32 40 | 41 | #define OPT_P_MIN 1 42 | #define OPT_P_MAX 1000 43 | #define OPT_P_DEF 20 44 | 45 | #define OPT_R_MIN 1 46 | #define OPT_R_MAX 10 47 | #define OPT_R_DEF 5 48 | 49 | #define OPT_S_MIN 1 50 | #define OPT_S_MAX 10 51 | #define OPT_S_DEF 5 52 | 53 | static volatile int g_pulse_count[MAX_GPIOS]; 54 | static volatile int g_reset_counts; 55 | static uint32_t g_mask; 56 | 57 | static int g_num_gpios; 58 | static int g_gpio[MAX_GPIOS]; 59 | 60 | static int g_opt_p = OPT_P_DEF; 61 | static int g_opt_r = OPT_R_DEF; 62 | static int g_opt_s = OPT_S_DEF; 63 | static int g_opt_t = 0; 64 | 65 | void usage() 66 | { 67 | fprintf 68 | (stderr, 69 | "\n" \ 70 | "Usage: sudo ./freq_count_1 gpio ... [OPTION] ...\n" \ 71 | " -p value, sets pulses every p micros, %d-%d, TESTING only\n" \ 72 | " -r value, sets refresh period in deciseconds, %d-%d, default %d\n" \ 73 | " -s value, sets sampling rate in micros, %d-%d, default %d\n" \ 74 | "\nEXAMPLE\n" \ 75 | "sudo ./freq_count_1 4 7 -r2 -s2\n" \ 76 | "Monitor gpios 4 and 7. Refresh every 0.2 seconds. Sample rate 2 micros.\n" \ 77 | "\n", 78 | OPT_P_MIN, OPT_P_MAX, 79 | OPT_R_MIN, OPT_R_MAX, OPT_R_DEF, 80 | OPT_S_MIN, OPT_S_MAX, OPT_S_DEF 81 | ); 82 | } 83 | 84 | void fatal(int show_usage, char *fmt, ...) 85 | { 86 | char buf[128]; 87 | va_list ap; 88 | 89 | va_start(ap, fmt); 90 | vsnprintf(buf, sizeof(buf), fmt, ap); 91 | va_end(ap); 92 | 93 | fprintf(stderr, "%s\n", buf); 94 | 95 | if (show_usage) usage(); 96 | 97 | fflush(stderr); 98 | 99 | exit(EXIT_FAILURE); 100 | } 101 | 102 | static int initOpts(int argc, char *argv[]) 103 | { 104 | int i, opt; 105 | 106 | while ((opt = getopt(argc, argv, "p:r:s:")) != -1) 107 | { 108 | i = -1; 109 | 110 | switch (opt) 111 | { 112 | case 'p': 113 | i = atoi(optarg); 114 | if ((i >= OPT_P_MIN) && (i <= OPT_P_MAX)) 115 | g_opt_p = i; 116 | else fatal(1, "invalid -p option (%d)", i); 117 | g_opt_t = 1; 118 | break; 119 | 120 | case 'r': 121 | i = atoi(optarg); 122 | if ((i >= OPT_R_MIN) && (i <= OPT_R_MAX)) 123 | g_opt_r = i; 124 | else fatal(1, "invalid -r option (%d)", i); 125 | break; 126 | 127 | case 's': 128 | i = atoi(optarg); 129 | if ((i >= OPT_S_MIN) && (i <= OPT_S_MAX)) 130 | g_opt_s = i; 131 | else fatal(1, "invalid -s option (%d)", i); 132 | break; 133 | 134 | default: /* '?' */ 135 | usage(); 136 | exit(-1); 137 | } 138 | } 139 | return optind; 140 | } 141 | 142 | void edges(int gpio, int level, uint32_t tick) 143 | { 144 | int g; 145 | 146 | if (g_reset_counts) 147 | { 148 | g_reset_counts = 0; 149 | for (g=0; g=0) && (g<32)) 174 | { 175 | g_gpio[g_num_gpios++] = g; 176 | g_mask |= (1< 2 | #include 3 | #include 4 | #include 5 | 6 | #include 7 | 8 | /* 9 | 2014-08-20 10 | 11 | gcc -o freq_count_2 freq_count_2.c -lpigpio -lpthread 12 | $ sudo ./freq_count_2 4 7 8 13 | 14 | This program uses the gpioSetGetSamplesFunc function to request 15 | a callback once a millisecond for all accumulated gpio changes 16 | in that millisecond. 17 | 18 | This tends to be more efficient then calling a callback for each 19 | gpio change during the millisecond. 20 | 21 | EXAMPLES 22 | 23 | Monitor gpio 4 (default settings) 24 | sudo ./freq_count_2 4 25 | 26 | Monitor gpios 4 and 8 (default settings) 27 | sudo ./freq_count_2 4 8 28 | 29 | Monitor gpios 4 and 8, sample rate 2 microseconds 30 | sudo ./freq_count_2 4 8 -s2 31 | 32 | Monitor gpios 7 and 8, sample rate 4 microseconds, report every second 33 | sudo ./freq_count_2 7 8 -s4 -r10 34 | 35 | Monitor gpios 4,7, 8, 9, 10, 23 24, report five times a second 36 | sudo ./freq_count_2 4 7 8 9 10 23 24 -r2 37 | 38 | Monitor gpios 4, 7, 8, and 9, report once a second, sample rate 1us, 39 | generate 2us edges (4us square wave, 250000 highs per second). 40 | sudo ./freq_count_2 4 7 8 9 -r 10 -s 1 -p 2 41 | 42 | */ 43 | 44 | #define MAX_GPIOS 32 45 | 46 | #define OPT_P_MIN 1 47 | #define OPT_P_MAX 1000 48 | #define OPT_P_DEF 20 49 | 50 | #define OPT_R_MIN 1 51 | #define OPT_R_MAX 10 52 | #define OPT_R_DEF 5 53 | 54 | #define OPT_S_MIN 1 55 | #define OPT_S_MAX 10 56 | #define OPT_S_DEF 5 57 | 58 | static volatile int g_pulse_count[MAX_GPIOS]; 59 | static volatile int g_reset_counts; 60 | static uint32_t g_mask; 61 | 62 | static int g_num_gpios; 63 | static int g_gpio[MAX_GPIOS]; 64 | 65 | static int g_opt_p = OPT_P_DEF; 66 | static int g_opt_r = OPT_R_DEF; 67 | static int g_opt_s = OPT_S_DEF; 68 | static int g_opt_t = 0; 69 | 70 | void usage() 71 | { 72 | fprintf 73 | (stderr, 74 | "\n" \ 75 | "Usage: sudo ./freq_count_2 gpio ... [OPTION] ...\n" \ 76 | " -p value, sets pulses every p micros, %d-%d, TESTING only\n" \ 77 | " -r value, sets refresh period in deciseconds, %d-%d, default %d\n" \ 78 | " -s value, sets sampling rate in micros, %d-%d, default %d\n" \ 79 | "\nEXAMPLE\n" \ 80 | "sudo ./freq_count_2 4 7 -r2 -s2\n" \ 81 | "Monitor gpios 4 and 7. Refresh every 0.2 seconds. Sample rate 2 micros.\n" \ 82 | "\n", 83 | OPT_P_MIN, OPT_P_MAX, 84 | OPT_R_MIN, OPT_R_MAX, OPT_R_DEF, 85 | OPT_S_MIN, OPT_S_MAX, OPT_S_DEF 86 | ); 87 | } 88 | 89 | void fatal(int show_usage, char *fmt, ...) 90 | { 91 | char buf[128]; 92 | va_list ap; 93 | 94 | va_start(ap, fmt); 95 | vsnprintf(buf, sizeof(buf), fmt, ap); 96 | va_end(ap); 97 | 98 | fprintf(stderr, "%s\n", buf); 99 | 100 | if (show_usage) usage(); 101 | 102 | fflush(stderr); 103 | 104 | exit(EXIT_FAILURE); 105 | } 106 | 107 | static int initOpts(int argc, char *argv[]) 108 | { 109 | int i, opt; 110 | 111 | while ((opt = getopt(argc, argv, "p:r:s:")) != -1) 112 | { 113 | i = -1; 114 | 115 | switch (opt) 116 | { 117 | case 'p': 118 | i = atoi(optarg); 119 | if ((i >= OPT_P_MIN) && (i <= OPT_P_MAX)) 120 | g_opt_p = i; 121 | else fatal(1, "invalid -p option (%d)", i); 122 | g_opt_t = 1; 123 | break; 124 | 125 | case 'r': 126 | i = atoi(optarg); 127 | if ((i >= OPT_R_MIN) && (i <= OPT_R_MAX)) 128 | g_opt_r = i; 129 | else fatal(1, "invalid -r option (%d)", i); 130 | break; 131 | 132 | case 's': 133 | i = atoi(optarg); 134 | if ((i >= OPT_S_MIN) && (i <= OPT_S_MAX)) 135 | g_opt_s = i; 136 | else fatal(1, "invalid -s option (%d)", i); 137 | break; 138 | 139 | default: /* '?' */ 140 | usage(); 141 | exit(-1); 142 | } 143 | } 144 | return optind; 145 | } 146 | 147 | void samples(const gpioSample_t *samples, int numSamples) 148 | { 149 | static uint32_t state = 0; 150 | uint32_t high, level; 151 | int g, s; 152 | 153 | if (g_reset_counts) 154 | { 155 | g_reset_counts = 0; 156 | for (g=0; g=0) && (g<32)) 193 | { 194 | g_gpio[g_num_gpios++] = g; 195 | g_mask |= (1< 2 | 3 | #include 4 | 5 | /* 6 | OH3144E or equivalent Hall effect sensor 7 | 8 | Pin 1 - 5V 9 | Pin 2 - Ground 10 | Pin 3 - gpio (here P1-8, gpio 14, TXD is used) 11 | 12 | The internal gpio pull-up is enabled so that the sensor 13 | normally reads high. It reads low when a magnet is close. 14 | 15 | gcc -o hall hall.c -lpigpio -lrt -lpthread 16 | sudo ./hall 17 | */ 18 | 19 | #define HALL 14 20 | 21 | void alert(int gpio, int level, uint32_t tick) 22 | { 23 | static uint32_t lastTick=0; 24 | 25 | if (lastTick) printf("%d %.2f\n", level, (float)(tick-lastTick)/1000000.0); 26 | else printf("%d 0.00\n", level); 27 | 28 | lastTick = tick; 29 | } 30 | 31 | int main(int argc, char *argv[]) 32 | { 33 | int secs=60; 34 | 35 | if (argc>1) secs = atoi(argv[1]); /* program run seconds */ 36 | 37 | if ((secs<1) || (secs>3600)) secs = 3600; 38 | 39 | if (gpioInitialise()<0) return 1; 40 | 41 | gpioSetMode(HALL, PI_INPUT); 42 | 43 | gpioSetPullUpDown(HALL, PI_PUD_UP); 44 | 45 | gpioSetAlertFunc(HALL, alert); 46 | 47 | sleep(secs); 48 | 49 | gpioTerminate(); 50 | } 51 | 52 | -------------------------------------------------------------------------------- /EXAMPLES/C/I2C_SNIFFER/README: -------------------------------------------------------------------------------- 1 | A program to passively sniff I2C transactions (100kHz bus maximum) and display the results. 2 | 3 | This C program uses pigpio notifications. 4 | 5 | -------------------------------------------------------------------------------- /EXAMPLES/C/I2C_SNIFFER/pig2i2c.c: -------------------------------------------------------------------------------- 1 | /* 2 | */ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #include "pigpio.h" 15 | 16 | /* 17 | This software reads pigpio notification reports monitoring the I2C signals. 18 | 19 | Notifications are pipe based so this software must be run on the Pi 20 | being monitored. 21 | 22 | It should be able to handle a 100kHz bus. You are unlikely to get any 23 | usable results if the bus is running at 400kHz. 24 | 25 | gcc -o pig2i2c pig2i2c.c 26 | 27 | Do something like 28 | 29 | sudo pigpiod -s 2 30 | 31 | # get a notification handle, assume handle 0 was returned 32 | 33 | pigs no 34 | 35 | # start notifications for SCL/SDA 36 | 37 | e.g. pigs nb 0 0x3 # Rev. 1 select gpios 0/1 38 | e.g. pigs nb 0 0xC # Rev. 2 select gpios 2/3 39 | e.g. pigs nb 0 0xA00 # select gpios 9/11 (1<<9|1<<11) 40 | 41 | # run the program, specifying SCL/SDA and notification pipe 42 | 43 | ./pig2i2c SCL SDA 2) 167 | { 168 | gSCL = atoi(argv[1]); 169 | gSDA = atoi(argv[2]); 170 | 171 | bSCL = 1< 2 | 3 | #include 4 | 5 | #include "ir_hasher.h" 6 | 7 | /* 8 | This code forms a hash over the IR pulses generated by an 9 | IR remote. 10 | 11 | The remote key press is not converted into a code in the manner of 12 | the lirc module. No attempt is made to decode the type of protocol 13 | used by the remote. The hash is likely to be unique for different 14 | keys and different remotes but this is not guaranteed. 15 | 16 | This hashing process works for some remotes/protocols but not for 17 | others. The only way to find out if it works for one or more of 18 | your remotes is to try it and see. 19 | */ 20 | 21 | struct _Pi_Hasher_s 22 | { 23 | int gpio; 24 | Pi_Hasher_CB_t callback; 25 | int timeout; 26 | int in_code; 27 | uint32_t hash_val; 28 | int edges; 29 | int t1; 30 | int t2; 31 | int t3; 32 | int t4; 33 | }; 34 | 35 | 36 | static uint32_t _hash(uint32_t hv, int old_val, int new_val) 37 | { 38 | int val; 39 | 40 | if (new_val < (old_val * 0.60)) val = 13; 41 | else if (old_val < (new_val * 0.60)) val = 23; 42 | else val = 2; 43 | 44 | hv ^= val; 45 | hv *= 16777619; /* FNV_PRIME_32 */ 46 | 47 | return hv; 48 | } 49 | 50 | static void _cb(int gpio, int level, uint32_t tick, void *user) 51 | { 52 | Pi_Hasher_t * hasher; 53 | 54 | hasher = user; 55 | 56 | if (level != PI_TIMEOUT) 57 | { 58 | if (hasher->in_code == 0) 59 | { 60 | hasher->in_code = 1; 61 | 62 | gpioSetWatchdog(gpio, hasher->timeout); 63 | 64 | hasher->hash_val = 2166136261U; /* FNV_BASIS_32 */ 65 | 66 | hasher->edges = 1; 67 | 68 | hasher->t1 = 0; 69 | hasher->t2 = 0; 70 | hasher->t3 = 0; 71 | hasher->t4 = tick; 72 | } 73 | else 74 | { 75 | hasher->edges++; 76 | 77 | hasher->t1 = hasher->t2; 78 | hasher->t2 = hasher->t3; 79 | hasher->t3 = hasher->t4; 80 | hasher->t4 = tick; 81 | 82 | if (hasher->edges > 3) 83 | { 84 | hasher->hash_val = 85 | _hash(hasher->hash_val, 86 | (hasher->t2)-(hasher->t1), 87 | (hasher->t4)-(hasher->t3)); 88 | } 89 | } 90 | } 91 | else 92 | { 93 | if (hasher->in_code) 94 | { 95 | hasher->in_code = 0; 96 | 97 | gpioSetWatchdog(gpio, 0); 98 | 99 | if (hasher->edges > 12) /* Anything less is probably noise. */ 100 | { 101 | (hasher->callback)(hasher->hash_val); 102 | } 103 | } 104 | } 105 | } 106 | 107 | Pi_Hasher_t *Pi_Hasher(int gpio, Pi_Hasher_CB_t callback, int timeout) 108 | { 109 | Pi_Hasher_t *hasher; 110 | 111 | hasher = malloc(sizeof(Pi_Hasher_t)); 112 | 113 | hasher->gpio = gpio; 114 | hasher->callback = callback; 115 | hasher->timeout = 5; 116 | 117 | hasher->in_code = 0; 118 | 119 | gpioSetMode(gpio, PI_INPUT); 120 | gpioSetAlertFuncEx(gpio, _cb, hasher); 121 | 122 | return hasher; 123 | } 124 | 125 | void Pi_Hasher_cancel(Pi_Hasher_t *hasher) 126 | { 127 | if (hasher) 128 | { 129 | gpioSetAlertFunc(hasher->gpio, 0); 130 | 131 | free(hasher); 132 | 133 | hasher = NULL; 134 | } 135 | } 136 | 137 | -------------------------------------------------------------------------------- /EXAMPLES/C/IR_RECEIVER/ir_hasher.h: -------------------------------------------------------------------------------- 1 | #ifndef IR_HASHER_H 2 | #define IR_HASHER_H 3 | 4 | #include 5 | 6 | typedef void (*Pi_Hasher_CB_t)(uint32_t); 7 | 8 | struct _Pi_Hasher_s; 9 | 10 | typedef struct _Pi_Hasher_s Pi_Hasher_t; 11 | 12 | Pi_Hasher_t * Pi_Hasher(int gpio, Pi_Hasher_CB_t callback, int timeout); 13 | /* 14 | This function establishes an IR hasher on the gpio. 15 | 16 | A gap of timeout milliseconds without a new bit indicates 17 | the end of a code. 18 | 19 | When code end is detected the callback function is called 20 | with the code hash. 21 | 22 | A pointer to a private data type is returned. This should be passed 23 | to Pi_Hasher_cancel if the hasher is to be cancelled. 24 | */ 25 | 26 | 27 | void Pi_Hasher_cancel(Pi_Hasher_t *hasher); 28 | /* 29 | This function releases the resources used by the hasher. 30 | */ 31 | 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /EXAMPLES/C/IR_RECEIVER/test_ir_hasher.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | #include "ir_hasher.h" 6 | 7 | /* 8 | 9 | REQUIRES 10 | 11 | An IR receiver output pin connected to a Pi gpio. 12 | 13 | TO BUILD 14 | 15 | gcc -o ir_hash_c test_ir_hasher.c ir_hasher.c -lpigpio -lrt -lpthread 16 | 17 | TO RUN 18 | 19 | sudo ./ir_hash_c 20 | 21 | */ 22 | 23 | void callback(uint32_t hash) 24 | { 25 | printf("hash=%u\n", hash); 26 | } 27 | 28 | int main(int argc, char *argv[]) 29 | { 30 | Pi_Hasher_t *hasher; 31 | 32 | if (gpioInitialise() < 0) return 1; 33 | 34 | /* 35 | This assumes the output pin of an IR receiver is 36 | connected to gpio 7. 37 | */ 38 | 39 | hasher = Pi_Hasher(7, callback, 5); 40 | 41 | sleep(300); 42 | 43 | Pi_Hasher_cancel(hasher); 44 | 45 | gpioTerminate(); 46 | } 47 | 48 | -------------------------------------------------------------------------------- /EXAMPLES/C/PCF8591_YL-40/PCF8591.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include /* libncurses5-dev */ 7 | 8 | /* 9 | 2014-08-26 PCF8591.c 10 | 11 | sudo apt-get install libncurses5-dev 12 | 13 | gcc -o PCF8591 PCF8591.c -lcurses -lpigpio -lpthread 14 | 15 | sudo ./PCF8591 16 | */ 17 | 18 | /* 19 | Connect Pi 3V3 - VCC, Ground - Ground, SDA - SDA, SCL - SCL. 20 | */ 21 | 22 | #define PCF8591_I2C_ADDR 0x48 23 | 24 | /* 25 | P4 The thermister voltage is provided at AIN 1. 26 | P5 The photocell voltage is provided at AIN 0. 27 | P6 The single turn 10K ohm trim pot voltage is provided at AIN 3. 28 | */ 29 | 30 | /* 31 | 7 6 5 4 3 2 1 0 32 | 0 X X X 0 X X X 33 | | | | | | | 34 | A B B C D D 35 | 36 | 0 1 0 0 0 1 0 0 37 | 38 | A 0 D/A inactive 39 | 1 D/A active 40 | 41 | B 00 single ended inputs 42 | 01 differential inputs 43 | 10 single ended and differential 44 | 11 two differential inputs 45 | 46 | C 0 no auto inc 47 | 1 auto inc 48 | 49 | D 00 select channel 0 50 | 01 select channel 1 51 | 10 select channel 2 52 | 11 select channel 3 53 | 54 | */ 55 | 56 | int main(int argc, char *argv[]) 57 | { 58 | int i; 59 | int r; 60 | int handle; 61 | char aout; 62 | unsigned char command[2]; 63 | unsigned char value[4]; 64 | unsigned char str[8]; 65 | 66 | int j; 67 | int key; 68 | 69 | if (gpioInitialise() < 0) return 1; 70 | 71 | initscr(); 72 | noecho(); 73 | cbreak(); 74 | nodelay(stdscr, true); 75 | curs_set(0); 76 | 77 | printw("PCF8591 + or - to change aout, any other key to quit."); 78 | 79 | mvaddstr(10, 0, "Brightness"); 80 | mvaddstr(12, 0, "Temperature"); 81 | mvaddstr(14, 0, "?"); 82 | mvaddstr(16, 0, "Resistor"); 83 | 84 | refresh(); 85 | 86 | handle = i2cOpen(1, PCF8591_I2C_ADDR, 0); 87 | 88 | command[1] = 0; 89 | aout = 128; 90 | 91 | while (1) 92 | { 93 | for (i=0; i<4; i++) 94 | { 95 | command[1] = aout; 96 | command[0] = 0x40 | ((i + 1) & 0x03); // output enable | read input i 97 | 98 | i2cWriteDevice(handle, &command, 2); 99 | 100 | usleep(20000); 101 | 102 | // the read is always one step behind the selected input 103 | value[i] = i2cReadByte(handle); 104 | 105 | sprintf(str, "%3d", value[i]); 106 | mvaddstr(10+i+i, 12, str); 107 | value[i] = value[i] / 4; 108 | move(10 + i + i, 16); 109 | 110 | for(j = 0; j < 64; j++) 111 | if(j < value[i]) addch('*'); else addch(' '); 112 | } 113 | 114 | refresh(); 115 | 116 | key = getch(); 117 | 118 | if ((key == '+') || (key == '=')) aout++; 119 | else if ((key == '-') || (key == '_')) aout--; 120 | else if (key != -1) break; 121 | } 122 | 123 | endwin(); 124 | 125 | i2cClose(handle); 126 | 127 | gpioTerminate(); 128 | 129 | return (0); 130 | } 131 | 132 | -------------------------------------------------------------------------------- /EXAMPLES/C/PCF8591_YL-40/README: -------------------------------------------------------------------------------- 1 | A program to display readings from the (I2C) PCF8591. 2 | -------------------------------------------------------------------------------- /EXAMPLES/C/POT_CAP_RECHARGE/README: -------------------------------------------------------------------------------- 1 | Function to time capacitor charging (through a resistance). 2 | 3 | The time can be used to estimate the resistance. 4 | -------------------------------------------------------------------------------- /EXAMPLES/C/POT_CAP_RECHARGE/pot_cap_charge.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | /* 6 | Measure how long a capacitor takes to charge through a resistance. 7 | 8 | A potentimeter is used to vary the resistance. 9 | 10 | The time taken will be proportional to the resistance. 11 | 12 | 3V3 ----- Potentiometer --+-- Capacitor ----- Ground 13 | | 14 | +-- gpio 15 | 16 | 17 | gcc -o pot_cap_charge pot_cap_charge.c -lpigpio -lpthread -lrt 18 | sudo ./pot_cap_charge 19 | 20 | */ 21 | 22 | #define GPIO 25 23 | 24 | #define MAX_READING 1000 25 | 26 | static uint32_t rechargeTick = 0; 27 | 28 | void callback(int gpio, int level, uint32_t tick) 29 | { 30 | static uint32_t smooth = 0; 31 | static int reading = 0; 32 | 33 | uint32_t raw; 34 | 35 | if (level == 1) /* measure recharge time */ 36 | { 37 | ++reading; 38 | 39 | if (rechargeTick) 40 | { 41 | raw = tick - rechargeTick; /* set in main */ 42 | 43 | if (raw < MAX_READING) /* ignore outliers */ 44 | { 45 | /* smooth using 0.8 * smooth + 0.2 * raw */ 46 | 47 | smooth = (raw + (4 * smooth)) / 5; 48 | 49 | printf("%d %d %d\n", reading, raw, smooth); 50 | } 51 | else 52 | { 53 | /* ignore outlier, set dot at fixed position */ 54 | printf("%d %d %d\n", reading, 40, smooth); 55 | } 56 | } 57 | else 58 | { 59 | /* ignore reschedule, set dot at fixed position */ 60 | printf("%d %d %d\n", reading, 20, smooth); 61 | } 62 | } 63 | } 64 | 65 | int main (int argc, char *argv[]) 66 | { 67 | uint32_t t1, t2; 68 | int tDiff; 69 | 70 | if (gpioInitialise()<0) return 1; 71 | 72 | gpioSetAlertFunc(GPIO, callback); /* callback when GPIO changes state */ 73 | 74 | while (1) 75 | { 76 | gpioWrite(GPIO, PI_OFF); /* drain capacitor */ 77 | 78 | gpioDelay(200); /* microseconds */ 79 | 80 | t1 = gpioTick(); 81 | 82 | gpioSetMode(GPIO, PI_INPUT); /* start capacitor recharge */ 83 | 84 | t2 = gpioTick(); 85 | 86 | /* dump reading if rechargeTick not accurate to 3 micros */ 87 | 88 | if ((t2 - t1) < 3) rechargeTick = t1; else rechargeTick = 0; 89 | 90 | gpioDelay(5000); /* microseconds, nominal 200 readings per second */ 91 | } 92 | 93 | gpioTerminate(); 94 | } 95 | -------------------------------------------------------------------------------- /EXAMPLES/C/ROTARY_ENCODER/README: -------------------------------------------------------------------------------- 1 | Function to decode a mechanical rotary encoder. 2 | 3 | Follow the instructions in the test file to build and run. 4 | 5 | -------------------------------------------------------------------------------- /EXAMPLES/C/ROTARY_ENCODER/rotary_encoder.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | 6 | #include "rotary_encoder.h" 7 | 8 | struct _Pi_Renc_s 9 | { 10 | int gpioA; 11 | int gpioB; 12 | Pi_Renc_CB_t callback; 13 | int levA; 14 | int levB; 15 | int lastGpio; 16 | }; 17 | 18 | /* 19 | 20 | +---------+ +---------+ 0 21 | | | | | 22 | A | | | | 23 | | | | | 24 | +---------+ +---------+ +----- 1 25 | 26 | +---------+ +---------+ 0 27 | | | | | 28 | B | | | | 29 | | | | | 30 | ----+ +---------+ +---------+ 1 31 | 32 | */ 33 | 34 | static void _cb(int gpio, int level, uint32_t tick, void *user) 35 | { 36 | Pi_Renc_t *renc; 37 | 38 | renc = user; 39 | 40 | if (gpio == renc->gpioA) renc->levA = level; else renc->levB = level; 41 | 42 | if (gpio != renc->lastGpio) /* debounce */ 43 | { 44 | renc->lastGpio = gpio; 45 | 46 | if ((gpio == renc->gpioA) && (level == 1)) 47 | { 48 | if (renc->levB) (renc->callback)(1); 49 | } 50 | else if ((gpio == renc->gpioB) && (level == 1)) 51 | { 52 | if (renc->levA) (renc->callback)(-1); 53 | } 54 | } 55 | } 56 | 57 | Pi_Renc_t * Pi_Renc(int gpioA, int gpioB, Pi_Renc_CB_t callback) 58 | { 59 | Pi_Renc_t *renc; 60 | 61 | renc = malloc(sizeof(Pi_Renc_t)); 62 | 63 | renc->gpioA = gpioA; 64 | renc->gpioB = gpioB; 65 | renc->callback = callback; 66 | renc->levA=0; 67 | renc->levB=0; 68 | renc->lastGpio = -1; 69 | 70 | gpioSetMode(gpioA, PI_INPUT); 71 | gpioSetMode(gpioB, PI_INPUT); 72 | 73 | /* pull up is needed as encoder common is grounded */ 74 | 75 | gpioSetPullUpDown(gpioA, PI_PUD_UP); 76 | gpioSetPullUpDown(gpioB, PI_PUD_UP); 77 | 78 | /* monitor encoder level changes */ 79 | 80 | gpioSetAlertFuncEx(gpioA, _cb, renc); 81 | gpioSetAlertFuncEx(gpioB, _cb, renc); 82 | } 83 | 84 | void Pi_Renc_cancel(Pi_Renc_t *renc) 85 | { 86 | if (renc) 87 | { 88 | gpioSetAlertFunc(renc->gpioA, 0); 89 | gpioSetAlertFunc(renc->gpioB, 0); 90 | 91 | free(renc); 92 | } 93 | } 94 | 95 | -------------------------------------------------------------------------------- /EXAMPLES/C/ROTARY_ENCODER/rotary_encoder.h: -------------------------------------------------------------------------------- 1 | #ifndef ROTARY_ENCODER_H 2 | #define ROTARY_ENCODER_H 3 | 4 | typedef void (*Pi_Renc_CB_t)(int); 5 | 6 | struct _Pi_Renc_s; 7 | 8 | typedef struct _Pi_Renc_s Pi_Renc_t; 9 | 10 | Pi_Renc_t * Pi_Renc(int gpioA, int gpioB, Pi_Renc_CB_t callback); 11 | /* 12 | This function establishes a rotary encoder on gpioA and gpioB. 13 | 14 | When the encoder is turned the callback function is called. 15 | 16 | A pointer to a private data type is returned. This should be passed 17 | to Pi_Renc_cancel if the rotary encoder is to be cancelled. 18 | */ 19 | 20 | void Pi_Renc_cancel(Pi_Renc_t *renc); 21 | /* 22 | This function releases the resources used by the decoder. 23 | */ 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /EXAMPLES/C/ROTARY_ENCODER/test_rotary_encoder.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | #include "rotary_encoder.h" 6 | 7 | /* 8 | 9 | REQUIRES 10 | 11 | A rotary encoder contacts A and B connected to separate gpios and 12 | the common contact connected to Pi ground. 13 | 14 | TO BUILD 15 | 16 | gcc -o rot_enc_c test_rotary_encoder.c rotary_encoder.c -lpigpio -lrt 17 | 18 | TO RUN 19 | 20 | sudo ./rot_enc_c 21 | 22 | */ 23 | 24 | void callback(int way) 25 | { 26 | static int pos = 0; 27 | 28 | pos += way; 29 | 30 | printf("pos=%d\n", pos); 31 | } 32 | 33 | int main(int argc, char *argv[]) 34 | { 35 | Pi_Renc_t * renc; 36 | 37 | if (gpioInitialise() < 0) return 1; 38 | 39 | renc = Pi_Renc(7, 8, callback); 40 | 41 | sleep(300); 42 | 43 | Pi_Renc_cancel(renc); 44 | 45 | gpioTerminate(); 46 | } 47 | 48 | -------------------------------------------------------------------------------- /EXAMPLES/C/WIEGAND_CODE/README: -------------------------------------------------------------------------------- 1 | Function to decode a Wiegand code. 2 | 3 | Follow the instructions in the test file to build and run. 4 | 5 | -------------------------------------------------------------------------------- /EXAMPLES/C/WIEGAND_CODE/test_wiegand.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | #include "wiegand.h" 6 | 7 | /* 8 | 9 | REQUIRES 10 | 11 | Wiegand contacts 0 and 1 connected to separate gpios. 12 | 13 | TO BUILD 14 | 15 | gcc -o wiegand_c test_wiegand.c wiegand.c -lpigpio -lrt 16 | 17 | TO RUN 18 | 19 | sudo ./wiegand_c 20 | 21 | */ 22 | 23 | void callback(int bits, uint32_t value) 24 | { 25 | printf("bits=%d value=%u\n", bits, value); 26 | } 27 | 28 | int main(int argc, char *argv[]) 29 | { 30 | Pi_Wieg_t * w; 31 | 32 | if (gpioInitialise() < 0) return 1; 33 | 34 | w = Pi_Wieg(14, 15, callback, 5); 35 | 36 | sleep(300); 37 | 38 | Pi_Wieg_cancel(w); 39 | 40 | gpioTerminate(); 41 | } 42 | 43 | -------------------------------------------------------------------------------- /EXAMPLES/C/WIEGAND_CODE/wiegand.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | #include "wiegand.h" 6 | 7 | struct _Pi_Wieg_s 8 | { 9 | int mygpio_0; 10 | int mygpio_1; 11 | int mytimeout; 12 | int in_code; 13 | int bits; 14 | Pi_Wieg_CB_t mycallback; 15 | uint32_t num; 16 | uint32_t code_timeout; 17 | }; 18 | 19 | void _cb(int gpio, int level, uint32_t tick, void *user) 20 | { 21 | /* 22 | Accumulate bits until both gpios 0 and 1 timeout. 23 | */ 24 | 25 | Pi_Wieg_t *wieg; 26 | 27 | wieg = user; 28 | 29 | if (level == 0) /* a falling edge indicates a new bit */ 30 | { 31 | if (!wieg->in_code) 32 | { 33 | wieg->bits = 1; 34 | wieg->num = 0; 35 | 36 | wieg->in_code = 1; 37 | wieg->code_timeout = 0; 38 | 39 | gpioSetWatchdog(wieg->mygpio_0, wieg->mytimeout); 40 | gpioSetWatchdog(wieg->mygpio_1, wieg->mytimeout); 41 | } 42 | else 43 | { 44 | wieg->bits++; 45 | wieg->num <<= 1; 46 | } 47 | 48 | if (gpio == wieg->mygpio_0) 49 | { 50 | wieg->code_timeout &= 2; /* clear gpio 0 timeout */ 51 | } 52 | else 53 | { 54 | wieg->code_timeout &= 1; /* clear gpio 1 timeout */ 55 | wieg->num |= 1; 56 | } 57 | } 58 | else if (level == PI_TIMEOUT) 59 | { 60 | if (wieg->in_code) 61 | { 62 | if (gpio == wieg->mygpio_0) 63 | { 64 | wieg->code_timeout |= 1; /* timeout gpio 0 */ 65 | } 66 | else 67 | { 68 | wieg->code_timeout |= 2; /* timeout gpio 1 */ 69 | } 70 | 71 | if (wieg->code_timeout == 3) /* both gpios timed out */ 72 | { 73 | gpioSetWatchdog(wieg->mygpio_0, 0); 74 | gpioSetWatchdog(wieg->mygpio_1, 0); 75 | 76 | wieg->in_code = 0; 77 | 78 | (wieg->mycallback)(wieg->bits, wieg->num); 79 | } 80 | } 81 | } 82 | } 83 | 84 | Pi_Wieg_t * Pi_Wieg( 85 | int gpio_0, 86 | int gpio_1, 87 | Pi_Wieg_CB_t callback, 88 | int timeout) 89 | { 90 | /* 91 | Instantiate with the gpio for 0 (green wire), the gpio for 1 92 | (white wire), the callback function, and the timeout in 93 | milliseconds which indicates the end of a code. 94 | 95 | The callback is passed the code length in bits and the value. 96 | */ 97 | 98 | Pi_Wieg_t *wieg; 99 | 100 | wieg = malloc(sizeof(Pi_Wieg_t)); 101 | 102 | wieg->mygpio_0 = gpio_0; 103 | wieg->mygpio_1 = gpio_1; 104 | 105 | wieg->mycallback = callback; 106 | 107 | wieg->mytimeout = timeout; 108 | 109 | wieg->in_code = 0; 110 | 111 | gpioSetMode(gpio_0, PI_INPUT); 112 | gpioSetMode(gpio_1, PI_INPUT); 113 | 114 | gpioSetPullUpDown(gpio_0, PI_PUD_UP); 115 | gpioSetPullUpDown(gpio_1, PI_PUD_UP); 116 | 117 | gpioSetAlertFuncEx(gpio_0, _cb, wieg); 118 | gpioSetAlertFuncEx(gpio_1, _cb, wieg); 119 | 120 | return wieg; 121 | } 122 | 123 | void Pi_Wieg_cancel(Pi_Wieg_t *wieg) 124 | { 125 | /* 126 | Cancel the Wiegand decoder. 127 | */ 128 | 129 | if (wieg) 130 | { 131 | gpioSetAlertFunc(wieg->mygpio_0, 0); 132 | gpioSetAlertFunc(wieg->mygpio_1, 0); 133 | 134 | free(wieg); 135 | } 136 | } 137 | 138 | -------------------------------------------------------------------------------- /EXAMPLES/C/WIEGAND_CODE/wiegand.h: -------------------------------------------------------------------------------- 1 | #ifndef WIEGAND_H 2 | #define WIEGAND_H 3 | 4 | #include 5 | 6 | typedef void (*Pi_Wieg_CB_t)(int, uint32_t); 7 | 8 | struct _Pi_Wieg_s; 9 | 10 | typedef struct _Pi_Wieg_s Pi_Wieg_t; 11 | 12 | Pi_Wieg_t *Pi_Wieg(int gpio_0, int gpio_1, Pi_Wieg_CB_t callback, int timeout); 13 | /* 14 | This function establishes a Wiegand decoder on gpio_0 and gpio_1. 15 | 16 | A gap of timeout milliseconds without a new bit indicates the 17 | end of a code. 18 | 19 | When the code is ended the callback function is called with the code 20 | bit length and value. 21 | 22 | A pointer to a private data type is returned. This should be passed 23 | to Pi_Wieg_cancel if the decoder is to be cancelled. 24 | */ 25 | 26 | void Pi_Wieg_cancel(Pi_Wieg_t *wieg); 27 | /* 28 | This function releases the resources used by the decoder. 29 | */ 30 | 31 | #endif 32 | 33 | -------------------------------------------------------------------------------- /EXAMPLES/CPP/IR_RECEIVER/README: -------------------------------------------------------------------------------- 1 | Class to hash a code from an IR receiver (reading an IR remote control). 2 | 3 | Follow the instructions in the test file to build and run. 4 | 5 | -------------------------------------------------------------------------------- /EXAMPLES/CPP/IR_RECEIVER/ir_hasher.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "ir_hasher.hpp" 4 | 5 | void Hasher::_hash(int old_val, int new_val) 6 | { 7 | int val; 8 | 9 | if (new_val < (old_val * 0.60)) val = 13; 10 | else if (old_val < (new_val * 0.60)) val = 23; 11 | else val = 2; 12 | 13 | hash_val ^= val; 14 | hash_val *= 16777619; /* FNV_PRIME_32 */ 15 | } 16 | 17 | void Hasher::_callback(int gpio, int level, uint32_t tick) 18 | { 19 | if (level != PI_TIMEOUT) 20 | { 21 | if (in_code == 0) 22 | { 23 | in_code = 1; 24 | 25 | gpioSetWatchdog(mygpio, mytimeout); 26 | 27 | hash_val = 2166136261U; /* FNV_BASIS_32 */ 28 | 29 | edges = 1; 30 | 31 | t1 = 0; 32 | t2 = 0; 33 | t3 = 0; 34 | t4 = tick; 35 | } 36 | else 37 | { 38 | edges++; 39 | 40 | t1 = t2; 41 | t2 = t3; 42 | t3 = t4; 43 | t4 = tick; 44 | 45 | if (edges > 3) _hash(t2-t1, t4-t3); 46 | } 47 | } 48 | else 49 | { 50 | if (in_code) 51 | { 52 | in_code = 0; 53 | 54 | gpioSetWatchdog(mygpio, 0); 55 | 56 | if (edges > 12) /* Anything less is probably noise. */ 57 | { 58 | (mycallback)(hash_val); 59 | } 60 | } 61 | } 62 | } 63 | 64 | void Hasher::_callbackExt(int gpio, int level, uint32_t tick, void *user) 65 | { 66 | /* 67 | Need a static callback to link with C. 68 | */ 69 | 70 | Hasher *mySelf = (Hasher *) user; 71 | 72 | mySelf->_callback(gpio, level, tick); /* Call the instance callback. */ 73 | } 74 | 75 | Hasher::Hasher(int gpio, HasherCB_t callback, int timeout) 76 | { 77 | /* 78 | Initialises an IR remote hasher on a gpio. A gap of timeout 79 | milliseconds indicates the end of the remote key press. 80 | */ 81 | mygpio = gpio; 82 | mycallback = callback; 83 | mytimeout = timeout; 84 | 85 | in_code = 0; 86 | 87 | gpioSetMode(gpio, PI_INPUT); 88 | 89 | gpioSetAlertFuncEx(gpio, _callbackExt, (void *)this); 90 | } 91 | 92 | -------------------------------------------------------------------------------- /EXAMPLES/CPP/IR_RECEIVER/ir_hasher.hpp: -------------------------------------------------------------------------------- 1 | #ifndef IR_RX_HASHER_HPP 2 | #define IR_RX_HASHER_HPP 3 | 4 | #include 5 | 6 | typedef void (*HasherCB_t)(uint32_t); 7 | 8 | class Hasher 9 | { 10 | 11 | /* 12 | This class forms a hash over the IR pulses generated by an 13 | IR remote. 14 | 15 | The remote key press is not converted into a code in the manner of 16 | the lirc module. No attempt is made to decode the type of protocol 17 | used by the remote. The hash is likely to be unique for different 18 | keys and different remotes but this is not guaranteed. 19 | 20 | This hashing process works for some remotes/protocols but not for 21 | others. The only way to find out if it works for one or more of 22 | your remotes is to try it and see. 23 | */ 24 | 25 | int mygpio, mytimeout; 26 | HasherCB_t mycallback; 27 | int in_code; 28 | uint32_t hash_val; 29 | int edges; 30 | uint32_t t1, t2, t3, t4; 31 | 32 | void _hash(int old_val, int new_val); 33 | void _callback(int gpio, int level, uint32_t tick); 34 | 35 | /* Need a static callback to link with C. */ 36 | static void _callbackExt(int gpio, int level, uint32_t tick, void *user); 37 | 38 | public: 39 | 40 | Hasher(int gpio, HasherCB_t callback, int timeout=5); 41 | }; 42 | 43 | #endif 44 | 45 | -------------------------------------------------------------------------------- /EXAMPLES/CPP/IR_RECEIVER/test_ir_hasher.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | #include "ir_hasher.hpp" 6 | 7 | /* 8 | 9 | REQUIRES 10 | 11 | An IR receiver output pin connected to a Pi gpio. 12 | 13 | TO BUILD 14 | 15 | g++ -o ir_hash_cpp test_ir_hasher.cpp ir_hasher.cpp -lpigpio -lrt -lpthread 16 | 17 | TO RUN 18 | 19 | sudo ./ir_hash_cpp 20 | 21 | */ 22 | 23 | void callback(uint32_t hash) 24 | { 25 | std::cout << "hash=" << hash << std::endl; 26 | } 27 | 28 | int main(int argc, char *argv[]) 29 | { 30 | if (gpioInitialise() >= 0) 31 | { 32 | /* Can't instantiate a Hasher before pigpio is initialised. */ 33 | 34 | /* 35 | This assumes the output pin of an IR receiver is 36 | connected to gpio 7. 37 | */ 38 | 39 | Hasher ir(7, callback); 40 | 41 | sleep(300); 42 | } 43 | } 44 | 45 | -------------------------------------------------------------------------------- /EXAMPLES/CPP/ROTARY_ENCODER/README: -------------------------------------------------------------------------------- 1 | Class to decode a mechanical rotary encoder. 2 | 3 | Follow the instructions in the test file to build and run. 4 | 5 | -------------------------------------------------------------------------------- /EXAMPLES/CPP/ROTARY_ENCODER/rotary_encoder.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | #include "rotary_encoder.hpp" 6 | 7 | /* 8 | 9 | +---------+ +---------+ 0 10 | | | | | 11 | A | | | | 12 | | | | | 13 | +---------+ +---------+ +----- 1 14 | 15 | +---------+ +---------+ 0 16 | | | | | 17 | B | | | | 18 | | | | | 19 | ----+ +---------+ +---------+ 1 20 | 21 | */ 22 | 23 | void re_decoder::_pulse(int gpio, int level, uint32_t tick) 24 | { 25 | if (gpio == mygpioA) levA = level; else levB = level; 26 | 27 | if (gpio != lastGpio) /* debounce */ 28 | { 29 | lastGpio = gpio; 30 | 31 | if ((gpio == mygpioA) && (level == 1)) 32 | { 33 | if (levB) (mycallback)(1); 34 | } 35 | else if ((gpio == mygpioB) && (level == 1)) 36 | { 37 | if (levA) (mycallback)(-1); 38 | } 39 | } 40 | } 41 | 42 | void re_decoder::_pulseEx(int gpio, int level, uint32_t tick, void *user) 43 | { 44 | /* 45 | Need a static callback to link with C. 46 | */ 47 | 48 | re_decoder *mySelf = (re_decoder *) user; 49 | 50 | mySelf->_pulse(gpio, level, tick); /* Call the instance callback. */ 51 | } 52 | 53 | re_decoder::re_decoder(int gpioA, int gpioB, re_decoderCB_t callback) 54 | { 55 | mygpioA = gpioA; 56 | mygpioB = gpioB; 57 | 58 | mycallback = callback; 59 | 60 | levA=0; 61 | levB=0; 62 | 63 | lastGpio = -1; 64 | 65 | gpioSetMode(gpioA, PI_INPUT); 66 | gpioSetMode(gpioB, PI_INPUT); 67 | 68 | /* pull up is needed as encoder common is grounded */ 69 | 70 | gpioSetPullUpDown(gpioA, PI_PUD_UP); 71 | gpioSetPullUpDown(gpioB, PI_PUD_UP); 72 | 73 | /* monitor encoder level changes */ 74 | 75 | gpioSetAlertFuncEx(gpioA, _pulseEx, this); 76 | gpioSetAlertFuncEx(gpioB, _pulseEx, this); 77 | } 78 | 79 | void re_decoder::re_cancel(void) 80 | { 81 | gpioSetAlertFuncEx(mygpioA, 0, this); 82 | gpioSetAlertFuncEx(mygpioB, 0, this); 83 | } 84 | 85 | -------------------------------------------------------------------------------- /EXAMPLES/CPP/ROTARY_ENCODER/rotary_encoder.hpp: -------------------------------------------------------------------------------- 1 | #ifndef ROTARY_ENCODER_HPP 2 | #define ROTARY_ENCODER_HPP 3 | 4 | #include 5 | 6 | typedef void (*re_decoderCB_t)(int); 7 | 8 | class re_decoder 9 | { 10 | int mygpioA, mygpioB, levA, levB, lastGpio; 11 | 12 | re_decoderCB_t mycallback; 13 | 14 | void _pulse(int gpio, int level, uint32_t tick); 15 | 16 | /* Need a static callback to link with C. */ 17 | static void _pulseEx(int gpio, int level, uint32_t tick, void *user); 18 | 19 | 20 | public: 21 | 22 | re_decoder(int gpioA, int gpioB, re_decoderCB_t callback); 23 | /* 24 | This function establishes a rotary encoder on gpioA and gpioB. 25 | 26 | When the encoder is turned the callback function is called. 27 | */ 28 | 29 | void re_cancel(void); 30 | /* 31 | This function releases the resources used by the decoder. 32 | */ 33 | }; 34 | 35 | #endif 36 | -------------------------------------------------------------------------------- /EXAMPLES/CPP/ROTARY_ENCODER/test_rotary_encoder.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | #include "rotary_encoder.hpp" 6 | 7 | /* 8 | 9 | REQUIRES 10 | 11 | A rotary encoder contacts A and B connected to separate gpios and 12 | the common contact connected to Pi ground. 13 | 14 | TO BUILD 15 | 16 | g++ -o rot_enc_cpp test_rotary_encoder.cpp rotary_encoder.cpp -lpigpio -lrt 17 | 18 | TO RUN 19 | 20 | sudo ./rot_enc_cpp 21 | 22 | */ 23 | 24 | void callback(int way) 25 | { 26 | static int pos = 0; 27 | 28 | pos += way; 29 | 30 | std::cout << "pos=" << pos << std::endl; 31 | } 32 | 33 | int main(int argc, char *argv[]) 34 | { 35 | if (gpioInitialise() < 0) return 1; 36 | 37 | re_decoder dec(7, 8, callback); 38 | 39 | sleep(3000); 40 | 41 | dec.re_cancel(); 42 | 43 | gpioTerminate(); 44 | } 45 | 46 | -------------------------------------------------------------------------------- /EXAMPLES/CPP/WIEGAND_CODE/README: -------------------------------------------------------------------------------- 1 | Class to decode a Wiegand code. 2 | 3 | Follow the instructions in the test file to build and run. 4 | -------------------------------------------------------------------------------- /EXAMPLES/CPP/WIEGAND_CODE/test_wiegand.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | #include "wiegand.hpp" 6 | 7 | /* 8 | 9 | REQUIRES 10 | 11 | Wiegand contacts 0 and 1 connected to separate gpios. 12 | 13 | TO BUILD 14 | 15 | g++ -o wiegand_cpp test_wiegand.cpp wiegand.cpp -lpigpio -lrt 16 | 17 | TO RUN 18 | 19 | sudo ./wiegand_cpp 20 | 21 | */ 22 | 23 | void callback(int bits, uint32_t value) 24 | { 25 | std::cout << "bits=" << bits << " value=" << value << std::endl; 26 | } 27 | 28 | int main(int argc, char *argv[]) 29 | { 30 | if (gpioInitialise() < 0) return 1; 31 | 32 | Wiegand dec(14, 15, callback); 33 | 34 | sleep(300); 35 | 36 | dec.cancel(); 37 | 38 | gpioTerminate(); 39 | } 40 | 41 | -------------------------------------------------------------------------------- /EXAMPLES/CPP/WIEGAND_CODE/wiegand.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "wiegand.hpp" 4 | 5 | Wiegand::Wiegand(int gpio_0, int gpio_1, WiegandCB_t callback, int timeout) 6 | { 7 | /* 8 | Instantiate with the gpio for 0 (green wire), the gpio for 1 9 | (white wire), the callback function, and the bit timeout in 10 | milliseconds which indicates the end of a code. 11 | 12 | The callback is passed the code length in bits and the value. 13 | */ 14 | 15 | mygpio_0 = gpio_0; 16 | mygpio_1 = gpio_1; 17 | 18 | mycallback = callback; 19 | 20 | mytimeout = timeout; 21 | 22 | in_code = 0; 23 | 24 | gpioSetMode(gpio_0, PI_INPUT); 25 | gpioSetMode(gpio_1, PI_INPUT); 26 | 27 | gpioSetPullUpDown(gpio_0, PI_PUD_UP); 28 | gpioSetPullUpDown(gpio_1, PI_PUD_UP); 29 | 30 | gpioSetAlertFuncEx(gpio_0, _cbEx, this); 31 | gpioSetAlertFuncEx(gpio_1, _cbEx, this); 32 | } 33 | 34 | void Wiegand::_cb(int gpio, int level, uint32_t tick) 35 | { 36 | /* 37 | Accumulate bits until both gpios 0 and 1 timeout. 38 | */ 39 | 40 | if (level == 0) /* a falling edge indicates a new bit */ 41 | { 42 | if (!in_code) 43 | { 44 | bits = 1; 45 | num = 0; 46 | 47 | in_code = 1; 48 | code_timeout = 0; 49 | 50 | gpioSetWatchdog(mygpio_0, mytimeout); 51 | gpioSetWatchdog(mygpio_1, mytimeout); 52 | } 53 | else 54 | { 55 | bits++; 56 | num <<= 1; 57 | } 58 | 59 | if (gpio == mygpio_0) 60 | { 61 | code_timeout &= 2; /* clear gpio 0 timeout */ 62 | } 63 | else 64 | { 65 | code_timeout &= 1; /* clear gpio 1 timeout */ 66 | num |= 1; 67 | } 68 | } 69 | else if (level == PI_TIMEOUT) 70 | { 71 | if (in_code) 72 | { 73 | if (gpio == mygpio_0) 74 | { 75 | code_timeout |= 1; /* timeout gpio 0 */ 76 | } 77 | else 78 | { 79 | code_timeout |= 2; /* timeout gpio 1 */ 80 | } 81 | 82 | if (code_timeout == 3) /* both gpios timed out */ 83 | { 84 | gpioSetWatchdog(mygpio_0, 0); 85 | gpioSetWatchdog(mygpio_1, 0); 86 | 87 | in_code = 0; 88 | 89 | (mycallback)(bits, num); 90 | } 91 | } 92 | } 93 | } 94 | 95 | void Wiegand::_cbEx(int gpio, int level, uint32_t tick, void *user) 96 | { 97 | /* 98 | Need a static callback to link with C. 99 | */ 100 | 101 | Wiegand *mySelf = (Wiegand *) user; 102 | 103 | mySelf->_cb(gpio, level, tick); /* Call the instance callback. */ 104 | } 105 | 106 | 107 | void Wiegand::cancel(void) 108 | { 109 | /* 110 | Cancel the Wiegand decoder. 111 | */ 112 | 113 | gpioSetAlertFuncEx(mygpio_0, 0, this); 114 | gpioSetAlertFuncEx(mygpio_1, 0, this); 115 | } 116 | 117 | -------------------------------------------------------------------------------- /EXAMPLES/CPP/WIEGAND_CODE/wiegand.hpp: -------------------------------------------------------------------------------- 1 | #ifndef WIEGAND_HPP 2 | #define WIEGAND_HPP 3 | 4 | #include 5 | 6 | typedef void (*WiegandCB_t)(int, uint32_t); 7 | 8 | class Wiegand 9 | { 10 | int mygpio_0, mygpio_1, mytimeout, in_code, bits; 11 | 12 | WiegandCB_t mycallback; 13 | 14 | uint32_t num; 15 | 16 | uint32_t code_timeout; 17 | 18 | void _cb(int gpio, int level, uint32_t tick); 19 | 20 | /* Need a static callback to link with C. */ 21 | static void _cbEx(int gpio, int level, uint32_t tick, void *user); 22 | 23 | public: 24 | 25 | Wiegand(int gpio_0, int gpio_1, WiegandCB_t callback, int timeout=5); 26 | /* 27 | This function establishes a Wiegand decoder on gpio_0 and gpio_1. 28 | 29 | A gap of timeout milliseconds without a new bit indicates 30 | the end of a code. 31 | 32 | When the code is ended the callback function is called with the code 33 | bit length and value. 34 | */ 35 | 36 | void cancel(void); 37 | /* 38 | This function releases the resources used by the decoder. 39 | */ 40 | }; 41 | 42 | #endif 43 | 44 | -------------------------------------------------------------------------------- /EXAMPLES/Python/DHT11_SENSOR/README: -------------------------------------------------------------------------------- 1 | Class to read the relative humidity and temperature from a DHT11 sensor. 2 | It implements the iterator python protocol. 3 | -------------------------------------------------------------------------------- /EXAMPLES/Python/DHT11_SENSOR/dht11.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | from __future__ import absolute_import, division, print_function, unicode_literals 5 | 6 | import time 7 | import pigpio 8 | 9 | 10 | class DHT11(object): 11 | """ 12 | The DHT11 class is a stripped version of the DHT22 sensor code by joan2937. 13 | You can find the initial implementation here: 14 | - https://github.com/srounet/pigpio/tree/master/EXAMPLES/Python/DHT22_AM2302_SENSOR 15 | 16 | example code: 17 | >>> pi = pigpio.pi() 18 | >>> sensor = DHT11(pi, 4) # 4 is the data GPIO pin connected to your sensor 19 | >>> for response in sensor: 20 | .... print("Temperature: {}".format(response['temperature'])) 21 | .... print("Humidity: {}".format(response['humidity'])) 22 | """ 23 | 24 | def __init__(self, pi, gpio): 25 | """ 26 | pi (pigpio): an instance of pigpio 27 | gpio (int): gpio pin number 28 | """ 29 | self.pi = pi 30 | self.gpio = gpio 31 | self.high_tick = 0 32 | self.bit = 40 33 | self.temperature = 0 34 | self.humidity = 0 35 | self.either_edge_cb = None 36 | self.setup() 37 | 38 | def setup(self): 39 | """ 40 | Clears the internal gpio pull-up/down resistor. 41 | Kills any watchdogs. 42 | """ 43 | self.pi.set_pull_up_down(self.gpio, pigpio.PUD_OFF) 44 | self.pi.set_watchdog(self.gpio, 0) 45 | self.register_callbacks() 46 | 47 | def register_callbacks(self): 48 | """ 49 | Monitors RISING_EDGE changes using callback. 50 | """ 51 | self.either_edge_cb = self.pi.callback( 52 | self.gpio, 53 | pigpio.EITHER_EDGE, 54 | self.either_edge_callback 55 | ) 56 | 57 | def either_edge_callback(self, gpio, level, tick): 58 | """ 59 | Either Edge callbacks, called each time the gpio edge changes. 60 | Accumulate the 40 data bits from the dht11 sensor. 61 | """ 62 | level_handlers = { 63 | pigpio.FALLING_EDGE: self._edge_FALL, 64 | pigpio.RISING_EDGE: self._edge_RISE, 65 | pigpio.EITHER_EDGE: self._edge_EITHER 66 | } 67 | handler = level_handlers[level] 68 | diff = pigpio.tickDiff(self.high_tick, tick) 69 | handler(tick, diff) 70 | 71 | def _edge_RISE(self, tick, diff): 72 | """ 73 | Handle Rise signal. 74 | """ 75 | val = 0 76 | if diff >= 50: 77 | val = 1 78 | if diff >= 200: # Bad bit? 79 | self.checksum = 256 # Force bad checksum 80 | 81 | if self.bit >= 40: # Message complete 82 | self.bit = 40 83 | elif self.bit >= 32: # In checksum byte 84 | self.checksum = (self.checksum << 1) + val 85 | if self.bit == 39: 86 | # 40th bit received 87 | self.pi.set_watchdog(self.gpio, 0) 88 | total = self.humidity + self.temperature 89 | # is checksum ok ? 90 | if not (total & 255) == self.checksum: 91 | raise 92 | elif 16 <= self.bit < 24: # in temperature byte 93 | self.temperature = (self.temperature << 1) + val 94 | elif 0 <= self.bit < 8: # in humidity byte 95 | self.humidity = (self.humidity << 1) + val 96 | else: # skip header bits 97 | pass 98 | self.bit += 1 99 | 100 | def _edge_FALL(self, tick, diff): 101 | """ 102 | Handle Fall signal. 103 | """ 104 | self.high_tick = tick 105 | if diff <= 250000: 106 | return 107 | self.bit = -2 108 | self.checksum = 0 109 | self.temperature = 0 110 | self.humidity = 0 111 | 112 | def _edge_EITHER(self, tick, diff): 113 | """ 114 | Handle Either signal. 115 | """ 116 | self.pi.set_watchdog(self.gpio, 0) 117 | 118 | def read(self): 119 | """ 120 | Start reading over DHT11 sensor. 121 | """ 122 | self.pi.write(self.gpio, pigpio.LOW) 123 | time.sleep(0.017) # 17 ms 124 | self.pi.set_mode(self.gpio, pigpio.INPUT) 125 | self.pi.set_watchdog(self.gpio, 200) 126 | time.sleep(0.2) 127 | 128 | def close(self): 129 | """ 130 | Stop reading sensor, remove callbacks. 131 | """ 132 | self.pi.set_watchdog(self.gpio, 0) 133 | if self.either_edge_cb: 134 | self.either_edge_cb.cancel() 135 | self.either_edge_cb = None 136 | 137 | def __iter__(self): 138 | """ 139 | Support the iterator protocol. 140 | """ 141 | return self 142 | 143 | def next(self): 144 | """ 145 | Call the read method and return temperature and humidity informations. 146 | """ 147 | self.read() 148 | response = { 149 | 'humidity': self.humidity, 150 | 'temperature': self.temperature 151 | } 152 | return response 153 | 154 | 155 | if __name__ == '__main__': 156 | pi = pigpio.pi() 157 | sensor = DHT11(pi, 4) 158 | for d in sensor: 159 | print("temperature: {}".format(d['temperature'])) 160 | print("humidity: {}".format(d['humidity'])) 161 | time.sleep(1) 162 | sensor.close() 163 | 164 | -------------------------------------------------------------------------------- /EXAMPLES/Python/DHT22_AM2302_SENSOR/README: -------------------------------------------------------------------------------- 1 | Class to read the relative humidity and temperature from a DHT22/AM2302 sensor. 2 | 3 | -------------------------------------------------------------------------------- /EXAMPLES/Python/GPIO_STATUS/README: -------------------------------------------------------------------------------- 1 | Script to display the status of gpios 0-31. 2 | 3 | -------------------------------------------------------------------------------- /EXAMPLES/Python/GPIO_STATUS/gpio_status.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import time 4 | import curses 5 | import atexit 6 | import sys 7 | 8 | import pigpio 9 | 10 | GPIOS=32 11 | 12 | MODES=["INPUT", "OUTPUT", "ALT5", "ALT4", "ALT0", "ALT1", "ALT2", "ALT3"] 13 | 14 | def cleanup(): 15 | curses.nocbreak() 16 | curses.echo() 17 | curses.endwin() 18 | pi.stop() 19 | 20 | pi = pigpio.pi() 21 | if not pi.connected: 22 | sys.exit(1) 23 | 24 | stdscr = curses.initscr() 25 | curses.noecho() 26 | curses.cbreak() 27 | 28 | atexit.register(cleanup) 29 | 30 | cb = [] 31 | 32 | for g in range(GPIOS): 33 | cb.append(pi.callback(g, pigpio.EITHER_EDGE)) 34 | 35 | # disable gpio 28 as the PCM clock is swamping the system 36 | 37 | cb[28].cancel() 38 | 39 | stdscr.nodelay(1) 40 | 41 | stdscr.addstr(0, 23, "Status of gpios 0-31", curses.A_REVERSE) 42 | 43 | while True: 44 | 45 | for g in range(GPIOS): 46 | tally = cb[g].tally() 47 | mode = pi.get_mode(g) 48 | 49 | col = (g // 11) * 25 50 | row = (g % 11) + 2 51 | 52 | stdscr.addstr(row, col, "{:2}".format(g), curses.A_BOLD) 53 | 54 | stdscr.addstr( 55 | "={} {:>6}: {:<10}".format(pi.read(g), MODES[mode], tally)) 56 | 57 | stdscr.refresh() 58 | 59 | time.sleep(0.1) 60 | 61 | c = stdscr.getch() 62 | 63 | if c != curses.ERR: 64 | break 65 | 66 | -------------------------------------------------------------------------------- /EXAMPLES/Python/HALL_EFFECT_SENSOR/README: -------------------------------------------------------------------------------- 1 | Program to show status changes for a Hall effect sensor. 2 | 3 | -------------------------------------------------------------------------------- /EXAMPLES/Python/HALL_EFFECT_SENSOR/hall.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import time 4 | 5 | import pigpio 6 | 7 | # 8 | # OH3144E or equivalent Hall effect sensor 9 | # 10 | # Pin 1 - 5V 11 | # Pin 2 - Ground 12 | # Pin 3 - gpio (here P1-8, gpio 14, TXD is used) 13 | # 14 | # The internal gpio pull-up is enabled so that the sensor 15 | # normally reads high. It reads low when a magnet is close. 16 | # 17 | 18 | HALL=14 19 | 20 | pi = pigpio.pi() # connect to local Pi 21 | 22 | pi.set_mode(HALL, pigpio.INPUT) 23 | pi.set_pull_up_down(HALL, pigpio.PUD_UP) 24 | 25 | start = time.time() 26 | 27 | while (time.time() - start) < 60: 28 | print("Hall = {}".format(pi.read(HALL))) 29 | time.sleep(0.2) 30 | 31 | pi.stop() 32 | 33 | -------------------------------------------------------------------------------- /EXAMPLES/Python/I2C_SNIFFER/I2C_sniffer.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import time 4 | 5 | import pigpio 6 | 7 | class sniffer: 8 | """ 9 | A class to passively monitor activity on an I2C bus. This should 10 | work for an I2C bus running at 100kbps or less. You are unlikely 11 | to get any usable results for a bus running any faster. 12 | """ 13 | 14 | def __init__(self, pi, SCL, SDA, set_as_inputs=True): 15 | """ 16 | Instantiate with the Pi and the gpios for the I2C clock 17 | and data lines. 18 | 19 | If you are monitoring one of the Raspberry Pi buses you 20 | must set set_as_inputs to False so that they remain in 21 | I2C mode. 22 | 23 | The pigpio daemon should have been started with a higher 24 | than default sample rate. 25 | 26 | For an I2C bus rate of 100Kbps sudo pigpiod -s 2 should work. 27 | 28 | A message is printed for each I2C transaction formatted with 29 | "[" for the START 30 | "XX" two hex characters for each data byte 31 | "+" if the data is ACKd, "-" if the data is NACKd 32 | "]" for the STOP 33 | 34 | E.g. Reading the X, Y, Z values from an ADXL345 gives: 35 | 36 | [A6+32+] 37 | [A7+01+FF+F2+FF+06+00-] 38 | """ 39 | 40 | self.pi = pi 41 | self.gSCL = SCL 42 | self.gSDA = SDA 43 | 44 | self.FALLING = 0 45 | self.RISING = 1 46 | self.STEADY = 2 47 | 48 | self.in_data = False 49 | self.byte = 0 50 | self.bit = 0 51 | self.oldSCL = 1 52 | self.oldSDA = 1 53 | 54 | self.transact = "" 55 | 56 | if set_as_inputs: 57 | self.pi.set_mode(SCL, pigpio.INPUT) 58 | self.pi.set_mode(SDA, pigpio.INPUT) 59 | 60 | self.cbA = self.pi.callback(SCL, pigpio.EITHER_EDGE, self._cb) 61 | self.cbB = self.pi.callback(SDA, pigpio.EITHER_EDGE, self._cb) 62 | 63 | def _parse(self, SCL, SDA): 64 | """ 65 | Accumulate all the data between START and STOP conditions 66 | into a string and output when STOP is detected. 67 | """ 68 | 69 | if SCL != self.oldSCL: 70 | self.oldSCL = SCL 71 | if SCL: 72 | xSCL = self.RISING 73 | else: 74 | xSCL = self.FALLING 75 | else: 76 | xSCL = self.STEADY 77 | 78 | if SDA != self.oldSDA: 79 | self.oldSDA = SDA 80 | if SDA: 81 | xSDA = self.RISING 82 | else: 83 | xSDA = self.FALLING 84 | else: 85 | xSDA = self.STEADY 86 | 87 | if xSCL == self.RISING: 88 | if self.in_data: 89 | if self.bit < 8: 90 | self.byte = (self.byte << 1) | SDA 91 | self.bit += 1 92 | else: 93 | self.transact += '{:02X}'.format(self.byte) 94 | if SDA: 95 | self.transact += '-' 96 | else: 97 | self.transact += '+' 98 | self.bit = 0 99 | self.byte = 0 100 | 101 | elif xSCL == self.STEADY: 102 | 103 | if xSDA == self.RISING: 104 | if SCL: 105 | self.in_data = False 106 | self.byte = 0 107 | self.bit = 0 108 | self.transact += ']' # STOP 109 | print (self.transact) 110 | self.transact = "" 111 | 112 | if xSDA == self.FALLING: 113 | if SCL: 114 | self.in_data = True 115 | self.byte = 0 116 | self.bit = 0 117 | self.transact += '[' # START 118 | 119 | def _cb(self, gpio, level, tick): 120 | """ 121 | Check which line has altered state (ignoring watchdogs) and 122 | call the parser with the new state. 123 | """ 124 | SCL = self.oldSCL 125 | SDA = self.oldSDA 126 | 127 | if gpio == self.gSCL: 128 | if level == 0: 129 | SCL = 0 130 | elif level == 1: 131 | SCL = 1 132 | 133 | if gpio == self.gSDA: 134 | if level == 0: 135 | SDA = 0 136 | elif level == 1: 137 | SDA = 1 138 | 139 | self._parse(SCL, SDA) 140 | 141 | def cancel(self): 142 | """Cancel the I2C callbacks.""" 143 | self.cbA.cancel() 144 | self.cbB.cancel() 145 | 146 | if __name__ == "__main__": 147 | 148 | import time 149 | 150 | import pigpio 151 | 152 | import I2C_sniffer 153 | 154 | pi = pigpio.pi() 155 | 156 | s = I2C_sniffer.sniffer(pi, 1, 0, False) # leave gpios 1/0 in I2C mode 157 | 158 | time.sleep(60000) 159 | 160 | s.cancel() 161 | 162 | pi.stop() 163 | 164 | -------------------------------------------------------------------------------- /EXAMPLES/Python/I2C_SNIFFER/README: -------------------------------------------------------------------------------- 1 | A program to passively sniff I2C transactions (100kHz bus maximum) and display the results. 2 | 3 | -------------------------------------------------------------------------------- /EXAMPLES/Python/IR_RECEIVER/README: -------------------------------------------------------------------------------- 1 | Class to hash a code from an IR receiver (reading an IR remote control). 2 | 3 | -------------------------------------------------------------------------------- /EXAMPLES/Python/IR_RECEIVER/ir_hasher.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import pigpio 4 | 5 | class hasher: 6 | 7 | """ 8 | This class forms a hash over the IR pulses generated by an 9 | IR remote. 10 | 11 | The remote key press is not converted into a code in the manner of 12 | the lirc module. No attempt is made to decode the type of protocol 13 | used by the remote. The hash is likely to be unique for different 14 | keys and different remotes but this is not guaranteed. 15 | 16 | This hashing process works for some remotes/protocols but not for 17 | others. The only way to find out if it works for one or more of 18 | your remotes is to try it and see. 19 | 20 | EXAMPLE CODE 21 | 22 | #!/usr/bin/env python 23 | 24 | import time 25 | import pigpio 26 | import ir_hasher 27 | 28 | def callback(hash): 29 | print("hash={}".format(hash)); 30 | 31 | pi = pigpio.pi() 32 | 33 | ir = ir_hasher.hasher(pi, 7, callback, 5) 34 | 35 | print("ctrl c to exit"); 36 | 37 | time.sleep(300) 38 | 39 | pi.stop() 40 | """ 41 | 42 | def __init__(self, pi, gpio, callback, timeout=5): 43 | 44 | """ 45 | Initialises an IR remote hasher on a pi's gpio. A gap of timeout 46 | milliseconds indicates the end of the remote key press. 47 | """ 48 | 49 | self.pi = pi 50 | self.gpio = gpio 51 | self.code_timeout = timeout 52 | self.callback = callback 53 | 54 | self.in_code = False 55 | 56 | pi.set_mode(gpio, pigpio.INPUT) 57 | 58 | self.cb = pi.callback(gpio, pigpio.EITHER_EDGE, self._cb) 59 | 60 | def _hash(self, old_val, new_val): 61 | 62 | if new_val < (old_val * 0.60): 63 | val = 13 64 | elif old_val < (new_val * 0.60): 65 | val = 23 66 | else: 67 | val = 2 68 | 69 | self.hash_val = self.hash_val ^ val 70 | self.hash_val *= 16777619 # FNV_PRIME_32 71 | self.hash_val = self.hash_val & ((1<<32)-1) 72 | 73 | def _cb(self, gpio, level, tick): 74 | 75 | if level != pigpio.TIMEOUT: 76 | 77 | if self.in_code == False: 78 | 79 | self.in_code = True 80 | 81 | self.pi.set_watchdog(self.gpio, self.code_timeout) 82 | 83 | self.hash_val = 2166136261 # FNV_BASIS_32 84 | 85 | self.edges = 1 86 | 87 | self.t1 = None 88 | self.t2 = None 89 | self.t3 = None 90 | self.t4 = tick 91 | 92 | else: 93 | 94 | self.edges += 1 95 | 96 | self.t1 = self.t2 97 | self.t2 = self.t3 98 | self.t3 = self.t4 99 | self.t4 = tick 100 | 101 | if self.t1 is not None: 102 | 103 | d1 = pigpio.tickDiff(self.t1,self.t2) 104 | d2 = pigpio.tickDiff(self.t3,self.t4) 105 | 106 | self._hash(d1, d2) 107 | 108 | else: 109 | 110 | if self.in_code: 111 | 112 | self.in_code = False 113 | 114 | self.pi.set_watchdog(self.gpio, 0) 115 | 116 | if self.edges > 12: 117 | 118 | self.callback(self.hash_val) 119 | 120 | if __name__ == "__main__": 121 | 122 | import time 123 | import pigpio 124 | import ir_hasher 125 | 126 | hashes = { 127 | 142650387: '2', 244341844: 'menu', 262513468: 'vol-', 128 | 272048826: '5', 345069212: '6', 363685443: 'prev.ch', 129 | 434191356: '1', 492745084: 'OK', 549497027: 'mute', 130 | 603729091: 'text', 646476378: 'chan-', 832916949: 'home', 131 | 923778138: 'power', 938165610: 'power', 953243510: 'forward', 132 | 1009731980:'1', 1018231875:'TV', 1142888517:'c-up', 133 | 1151589683:'chan+', 1344018636:'OK', 1348032067:'chan+', 134 | 1367109971:'prev.ch', 1370712102:'c-left', 1438405361:'rewind', 135 | 1452589043:'pause', 1518578730:'chan-', 1554432645:'8', 136 | 1583569525:'0', 1629745313:'rewind', 1666513749:'record', 137 | 1677653754:'c-down', 1825951717:'c-right', 1852412236:'6', 138 | 1894279468:'9', 1904895749:'vol+', 1941947509:'ff', 139 | 2076573637:'0', 2104823531:'back', 2141641957:'home', 140 | 2160787557:'record', 2398525299:'7', 2468117013:'8', 141 | 2476712746:'play', 2574308838:'forward', 2577952149:'4', 142 | 2706654902:'stop', 2829002741:'c-up', 2956097083:'back', 143 | 3112717386:'5', 3263244773:'ff', 3286088195:'pause', 144 | 3363767978:'c-down', 3468076364:'vol-', 3491068358:'stop', 145 | 3593710134:'c-left', 3708232515:'3', 3734134565:'back', 146 | 3766109107:'TV', 3798010010:'play', 3869937700:'menu', 147 | 3872715523:'7', 3885097091:'2', 3895301587:'text', 148 | 3931058739:'mute', 3983900853:'c-right', 4032250885:'4', 149 | 4041913909:'vol+', 4207017660:'9', 4227138677:'back', 150 | 4294027955:'3'} 151 | 152 | def callback(hash): 153 | if hash in hashes: 154 | print("key={} hash={}".format(hashes[hash], hash)); 155 | 156 | pi = pigpio.pi() 157 | 158 | ir = ir_hasher.hasher(pi, 7, callback, 5) 159 | 160 | print("ctrl c to exit"); 161 | 162 | time.sleep(300) 163 | 164 | pi.stop() 165 | 166 | -------------------------------------------------------------------------------- /EXAMPLES/Python/MORSE_CODE/README: -------------------------------------------------------------------------------- 1 | Script to transmit the morse code corresponding to a text string. 2 | 3 | -------------------------------------------------------------------------------- /EXAMPLES/Python/MORSE_CODE/morse_code.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import pigpio 4 | 5 | morse={ 6 | 'a':'.-' , 'b':'-...' , 'c':'-.-.' , 'd':'-..' , 'e':'.' , 7 | 'f':'..-.' , 'g':'--.' , 'h':'....' , 'i':'..' , 'j':'.---' , 8 | 'k':'-.-' , 'l':'.-..' , 'm':'--' , 'n':'-.' , 'o':'---' , 9 | 'p':'.--.' , 'q':'--.-' , 'r':'.-.' , 's':'...' , 't':'-' , 10 | 'u':'..-' , 'v':'...-' , 'w':'.--' , 'x':'-..-' , 'y':'-.--' , 11 | 'z':'--..' , '1':'.----', '2':'..---', '3':'...--', '4':'....-', 12 | '5':'.....', '6':'-....', '7':'--...', '8':'---..', '9':'----.', 13 | '0':'-----'} 14 | 15 | GPIO=22 16 | 17 | MICROS=100000 18 | 19 | NONE=0 20 | 21 | DASH=3 22 | DOT=1 23 | 24 | GAP=1 25 | LETTER_GAP=3-GAP 26 | WORD_GAP=7-LETTER_GAP 27 | 28 | def transmit_string(pi, gpio, str): 29 | 30 | pi.wave_clear() # start a new waveform 31 | 32 | wf=[] 33 | 34 | for C in str: 35 | c=C.lower() 36 | print(c) 37 | if c in morse: 38 | k = morse[c] 39 | for x in k: 40 | 41 | if x == '.': 42 | wf.append(pigpio.pulse(1<AIN2") 31 | stdscr.addstr(16, 0, "Resistor") 32 | 33 | stdscr.nodelay(1) 34 | 35 | try: 36 | while True: 37 | 38 | for a in range(0,4): 39 | aout = aout + 1 40 | pi.i2c_write_byte_data(handle, 0x40 | ((a+1) & 0x03), aout&0xFF) 41 | v = pi.i2c_read_byte(handle) 42 | hashes = v / 4 43 | spaces = 64 - hashes 44 | stdscr.addstr(10+a*2, 12, str(v) + ' ') 45 | stdscr.addstr(10+a*2, 16, '#' * hashes + ' ' * spaces ) 46 | 47 | stdscr.refresh() 48 | time.sleep(0.04) 49 | 50 | c = stdscr.getch() 51 | 52 | if c != curses.ERR: 53 | break 54 | 55 | except: 56 | pass 57 | 58 | curses.nocbreak() 59 | curses.echo() 60 | curses.endwin() 61 | 62 | pi.i2c_close(handle) 63 | pi.stop() 64 | 65 | -------------------------------------------------------------------------------- /EXAMPLES/Python/PCF8591_YL-40/README: -------------------------------------------------------------------------------- 1 | Script to display readings from the (I2C) PCF8591. 2 | 3 | -------------------------------------------------------------------------------- /EXAMPLES/Python/PIGPIO_BENCHMARK/README: -------------------------------------------------------------------------------- 1 | Script to benchmark the pigpio Python module's performance. 2 | 3 | -------------------------------------------------------------------------------- /EXAMPLES/Python/PIGPIO_BENCHMARK/bench_1.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | # 4 | # WARNING! 5 | # 6 | 7 | ############################################################################## 8 | # # 9 | # Unless you know what you are doing don't run this script with anything # 10 | # connected to the gpios. You will CAUSE damage. # 11 | # # 12 | ############################################################################## 13 | 14 | # 15 | # WARNING! 16 | # 17 | 18 | import time 19 | 20 | import pigpio 21 | 22 | delay = 30 23 | 24 | class gpioTest: 25 | 26 | def __init__(self, pi, gpio, edge, freq, duty): 27 | self.pi = pi 28 | self.gpio = gpio 29 | self.edge = edge 30 | self.freq = freq 31 | self.duty = duty 32 | self.calls = 0 33 | 34 | def cb(self, g, t, l): 35 | self.calls = self.calls + 1 36 | # print g,t,l 37 | 38 | def num(self): 39 | return self.calls 40 | 41 | def start(self): 42 | self.pi.set_PWM_frequency(self.gpio, self.freq) 43 | self.pi.set_PWM_range(self.gpio, 25) 44 | self.pi.set_PWM_dutycycle(self.gpio, self.duty) 45 | self.n = self.pi.callback(self.gpio, self.edge, self.cb) 46 | 47 | def stop(self): 48 | self.pi.set_PWM_dutycycle(self.gpio, 0) 49 | self.n.cancel() 50 | 51 | pi = pigpio.pi() 52 | 53 | t1 = gpioTest(pi, 4, pigpio.EITHER_EDGE, 4000, 1) 54 | t2 = gpioTest(pi, 7, pigpio.RISING_EDGE, 8000, 2) 55 | t3 = gpioTest(pi, 8, pigpio.FALLING_EDGE, 8000, 3) 56 | t4 = gpioTest(pi, 9, pigpio.EITHER_EDGE, 4000, 4) 57 | t5 = gpioTest(pi,10, pigpio.RISING_EDGE, 8000, 5) 58 | t6 = gpioTest(pi,11, pigpio.FALLING_EDGE, 8000, 6) 59 | t7 = gpioTest(pi,14, pigpio.EITHER_EDGE, 4000, 7) 60 | t8 = gpioTest(pi,15, pigpio.RISING_EDGE, 8000, 8) 61 | t9 = gpioTest(pi,17, pigpio.FALLING_EDGE, 8000, 9) 62 | t10 = gpioTest(pi,18, pigpio.EITHER_EDGE, 4000, 10) 63 | t11 = gpioTest(pi,22, pigpio.RISING_EDGE, 8000, 11) 64 | t12 = gpioTest(pi,23, pigpio.FALLING_EDGE, 8000, 12) 65 | t13 = gpioTest(pi,24, pigpio.EITHER_EDGE, 4000, 13) 66 | t14 = gpioTest(pi,25, pigpio.RISING_EDGE, 8000, 14) 67 | 68 | # R1: 0 1 4 7 8 9 10 11 14 15 17 18 21 22 23 24 25 69 | # R2: 2 3 4 7 8 9 10 11 14 15 17 18 22 23 24 25 27 28 29 30 31 70 | 71 | tests = [t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14] 72 | 73 | for i in tests: i.start() 74 | 75 | time.sleep(delay) 76 | 77 | for i in tests: i.stop() 78 | 79 | pi.stop() 80 | 81 | tot = 0 82 | msg = "" 83 | 84 | for i in tests: 85 | tot += i.num() 86 | msg += str(i.num()) + " " 87 | 88 | print(msg) 89 | 90 | print("eps={} ({}/{})".format(tot/delay, tot, delay)) 91 | 92 | -------------------------------------------------------------------------------- /EXAMPLES/Python/ROTARY_ENCODER/README: -------------------------------------------------------------------------------- 1 | Class to decode a mechanical rotary encoder. 2 | 3 | -------------------------------------------------------------------------------- /EXAMPLES/Python/ROTARY_ENCODER/rotary_encoder.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import pigpio 4 | 5 | class decoder: 6 | 7 | """Class to decode mechanical rotary encoder pulses.""" 8 | 9 | def __init__(self, pi, gpioA, gpioB, callback): 10 | 11 | """ 12 | Instantiate the class with the pi and gpios connected to 13 | rotary encoder contacts A and B. The common contact 14 | should be connected to ground. The callback is 15 | called when the rotary encoder is turned. It takes 16 | one parameter which is +1 for clockwise and -1 for 17 | counterclockwise. 18 | 19 | EXAMPLE 20 | 21 | import time 22 | import pigpio 23 | 24 | import rotary_encoder 25 | 26 | pos = 0 27 | 28 | def callback(way): 29 | 30 | global pos 31 | 32 | pos += way 33 | 34 | print("pos={}".format(pos)) 35 | 36 | pi = pigpio.pi() 37 | 38 | decoder = rotary_encoder.decoder(pi, 7, 8, callback) 39 | 40 | time.sleep(300) 41 | 42 | decoder.cancel() 43 | 44 | pi.stop() 45 | 46 | """ 47 | 48 | self.pi = pi 49 | self.gpioA = gpioA 50 | self.gpioB = gpioB 51 | self.callback = callback 52 | 53 | self.levA = 0 54 | self.levB = 0 55 | 56 | self.lastGpio = None 57 | 58 | self.pi.set_mode(gpioA, pigpio.INPUT) 59 | self.pi.set_mode(gpioB, pigpio.INPUT) 60 | 61 | self.pi.set_pull_up_down(gpioA, pigpio.PUD_UP) 62 | self.pi.set_pull_up_down(gpioB, pigpio.PUD_UP) 63 | 64 | self.cbA = self.pi.callback(gpioA, pigpio.EITHER_EDGE, self._pulse) 65 | self.cbB = self.pi.callback(gpioB, pigpio.EITHER_EDGE, self._pulse) 66 | 67 | def _pulse(self, gpio, level, tick): 68 | 69 | """ 70 | Decode the rotary encoder pulse. 71 | 72 | +---------+ +---------+ 0 73 | | | | | 74 | A | | | | 75 | | | | | 76 | +---------+ +---------+ +----- 1 77 | 78 | +---------+ +---------+ 0 79 | | | | | 80 | B | | | | 81 | | | | | 82 | ----+ +---------+ +---------+ 1 83 | """ 84 | 85 | if gpio == self.gpioA: 86 | self.levA = level 87 | else: 88 | self.levB = level; 89 | 90 | if gpio != self.lastGpio: # debounce 91 | self.lastGpio = gpio 92 | 93 | if gpio == self.gpioA and level == 1: 94 | if self.levB == 1: 95 | self.callback(1) 96 | elif gpio == self.gpioB and level == 1: 97 | if self.levA == 1: 98 | self.callback(-1) 99 | 100 | def cancel(self): 101 | 102 | """ 103 | Cancel the rotary encoder decoder. 104 | """ 105 | 106 | self.cbA.cancel() 107 | self.cbB.cancel() 108 | 109 | if __name__ == "__main__": 110 | 111 | import time 112 | import pigpio 113 | 114 | import rotary_encoder 115 | 116 | pos = 0 117 | 118 | def callback(way): 119 | 120 | global pos 121 | 122 | pos += way 123 | 124 | print("pos={}".format(pos)) 125 | 126 | pi = pigpio.pi() 127 | 128 | decoder = rotary_encoder.decoder(pi, 7, 8, callback) 129 | 130 | time.sleep(300) 131 | 132 | decoder.cancel() 133 | 134 | pi.stop() 135 | 136 | -------------------------------------------------------------------------------- /EXAMPLES/Python/SENT_PROTOCOL/README.md: -------------------------------------------------------------------------------- 1 | # Python Class for Reading Single Edge Nibble Transmission (SENT) using the Raspberry Pi 2 | 3 | A full description of this Python script is described at [www.surfncircuits.com](https://surfncircuits.com) in the blog entry: [Implementing a Single Edge Nibble Transmission (SENT) protocol in Python for the Raspberry Pi Zero](https://surfncircuits.com/?p=3725) 4 | 5 | 6 | This python library will read a Raspberry Pi GPIO pin connected. Start the pigpiod daemon with one microsecond sampling to read SENT transmissions with three microsecond tick times. 7 | 8 | ## To start the daemon on Raspberry Pi 9 | - sudo pigpiod -s 1 10 | 11 | ## SENT packet frame summary 12 | 13 | - Sync Pulse: 56 ticks 14 | - 4 bit Status and Message Pulse: 17-32 ticks 15 | - 4 bit (9:12) Data1 Field: 17-32 ticks 16 | - 4 bit (5:8) Data1 Field: 17-32 ticks 17 | - 4 bit (1:4) Data1 Field: 17-32 ticks 18 | - 4 bit (9-12) Data2 Field: 17-32 ticks 19 | - 4 bit (5-8) Data2 Field: 17-32 ticks 20 | - 4 bit (1-4) Data2 Field: 17-32 ticks 21 | - 4 bit CRC: 17-32 ticks 22 | 23 | 24 | ## requirements 25 | [pigpiod](http://abyz.me.uk/rpi/pigpio/) library required 26 | 27 | ## To run the script for a signal attached to GPIO BCD 18 (pin 12) 28 | - python3 sent_READ.py 29 | -------------------------------------------------------------------------------- /EXAMPLES/Python/SONAR_RANGER/README: -------------------------------------------------------------------------------- 1 | Class to read sonar rangers with separate trigger and echo pins. 2 | 3 | -------------------------------------------------------------------------------- /EXAMPLES/Python/SONAR_RANGER/sonar_trigger_echo.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import time 4 | 5 | import pigpio 6 | 7 | class ranger: 8 | """ 9 | This class encapsulates a type of acoustic ranger. In particular 10 | the type of ranger with separate trigger and echo pins. 11 | 12 | A pulse on the trigger initiates the sonar ping and shortly 13 | afterwards a sonar pulse is transmitted and the echo pin 14 | goes high. The echo pins stays high until a sonar echo is 15 | received (or the response times-out). The time between 16 | the high and low edges indicates the sonar round trip time. 17 | """ 18 | 19 | def __init__(self, pi, trigger, echo): 20 | """ 21 | The class is instantiated with the Pi to use and the 22 | gpios connected to the trigger and echo pins. 23 | """ 24 | self.pi = pi 25 | self._trig = trigger 26 | self._echo = echo 27 | 28 | self._ping = False 29 | self._high = None 30 | self._time = None 31 | 32 | self._triggered = False 33 | 34 | self._trig_mode = pi.get_mode(self._trig) 35 | self._echo_mode = pi.get_mode(self._echo) 36 | 37 | pi.set_mode(self._trig, pigpio.OUTPUT) 38 | pi.set_mode(self._echo, pigpio.INPUT) 39 | 40 | self._cb = pi.callback(self._trig, pigpio.EITHER_EDGE, self._cbf) 41 | self._cb = pi.callback(self._echo, pigpio.EITHER_EDGE, self._cbf) 42 | 43 | self._inited = True 44 | 45 | def _cbf(self, gpio, level, tick): 46 | if gpio == self._trig: 47 | if level == 0: # trigger sent 48 | self._triggered = True 49 | self._high = None 50 | else: 51 | if self._triggered: 52 | if level == 1: 53 | self._high = tick 54 | else: 55 | if self._high is not None: 56 | self._time = tick - self._high 57 | self._high = None 58 | self._ping = True 59 | 60 | def read(self): 61 | """ 62 | Triggers a reading. The returned reading is the number 63 | of microseconds for the sonar round-trip. 64 | 65 | round trip cms = round trip time / 1000000.0 * 34030 66 | """ 67 | if self._inited: 68 | self._ping = False 69 | self.pi.gpio_trigger(self._trig) 70 | start = time.time() 71 | while not self._ping: 72 | if (time.time()-start) > 5.0: 73 | return 20000 74 | time.sleep(0.001) 75 | return self._time 76 | else: 77 | return None 78 | 79 | def cancel(self): 80 | """ 81 | Cancels the ranger and returns the gpios to their 82 | original mode. 83 | """ 84 | if self._inited: 85 | self._inited = False 86 | self._cb.cancel() 87 | self.pi.set_mode(self._trig, self._trig_mode) 88 | self.pi.set_mode(self._echo, self._echo_mode) 89 | 90 | if __name__ == "__main__": 91 | 92 | import time 93 | 94 | import pigpio 95 | 96 | import sonar_trigger_echo 97 | 98 | pi = pigpio.pi() 99 | 100 | sonar = sonar_trigger_echo.ranger(pi, 23, 18) 101 | 102 | end = time.time() + 600.0 103 | 104 | r = 1 105 | while time.time() < end: 106 | 107 | print("{} {}".format(r, sonar.read())) 108 | r += 1 109 | time.sleep(0.03) 110 | 111 | sonar.cancel() 112 | 113 | pi.stop() 114 | 115 | -------------------------------------------------------------------------------- /EXAMPLES/Python/VIRTUAL_WIRE/README: -------------------------------------------------------------------------------- 1 | Class to send and receive radio messages compatible with the Virtual Wire library for Arduinos. 2 | 3 | -------------------------------------------------------------------------------- /EXAMPLES/Python/WIEGAND_CODE/README: -------------------------------------------------------------------------------- 1 | Class to decode a Wiegand code. 2 | 3 | -------------------------------------------------------------------------------- /EXAMPLES/Python/WIEGAND_CODE/wiegand.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import pigpio 4 | 5 | class decoder: 6 | 7 | """ 8 | A class to read Wiegand codes of an arbitrary length. 9 | 10 | The code length and value are returned. 11 | 12 | EXAMPLE 13 | 14 | #!/usr/bin/env python 15 | 16 | import time 17 | 18 | import pigpio 19 | 20 | import wiegand 21 | 22 | def callback(bits, code): 23 | print("bits={} code={}".format(bits, code)) 24 | 25 | pi = pigpio.pi() 26 | 27 | w = wiegand.decoder(pi, 14, 15, callback) 28 | 29 | time.sleep(300) 30 | 31 | w.cancel() 32 | 33 | pi.stop() 34 | """ 35 | 36 | def __init__(self, pi, gpio_0, gpio_1, callback, bit_timeout=5): 37 | 38 | """ 39 | Instantiate with the pi, gpio for 0 (green wire), the gpio for 1 40 | (white wire), the callback function, and the bit timeout in 41 | milliseconds which indicates the end of a code. 42 | 43 | The callback is passed the code length in bits and the value. 44 | """ 45 | 46 | self.pi = pi 47 | self.gpio_0 = gpio_0 48 | self.gpio_1 = gpio_1 49 | 50 | self.callback = callback 51 | 52 | self.bit_timeout = bit_timeout 53 | 54 | self.in_code = False 55 | 56 | self.pi.set_mode(gpio_0, pigpio.INPUT) 57 | self.pi.set_mode(gpio_1, pigpio.INPUT) 58 | 59 | self.pi.set_pull_up_down(gpio_0, pigpio.PUD_UP) 60 | self.pi.set_pull_up_down(gpio_1, pigpio.PUD_UP) 61 | 62 | self.cb_0 = self.pi.callback(gpio_0, pigpio.FALLING_EDGE, self._cb) 63 | self.cb_1 = self.pi.callback(gpio_1, pigpio.FALLING_EDGE, self._cb) 64 | 65 | def _cb(self, gpio, level, tick): 66 | 67 | """ 68 | Accumulate bits until both gpios 0 and 1 timeout. 69 | """ 70 | 71 | if level < pigpio.TIMEOUT: 72 | 73 | if self.in_code == False: 74 | self.bits = 1 75 | self.num = 0 76 | 77 | self.in_code = True 78 | self.code_timeout = 0 79 | self.pi.set_watchdog(self.gpio_0, self.bit_timeout) 80 | self.pi.set_watchdog(self.gpio_1, self.bit_timeout) 81 | else: 82 | self.bits += 1 83 | self.num = self.num << 1 84 | 85 | if gpio == self.gpio_0: 86 | self.code_timeout = self.code_timeout & 2 # clear gpio 0 timeout 87 | else: 88 | self.code_timeout = self.code_timeout & 1 # clear gpio 1 timeout 89 | self.num = self.num | 1 90 | 91 | else: 92 | 93 | if self.in_code: 94 | 95 | if gpio == self.gpio_0: 96 | self.code_timeout = self.code_timeout | 1 # timeout gpio 0 97 | else: 98 | self.code_timeout = self.code_timeout | 2 # timeout gpio 1 99 | 100 | if self.code_timeout == 3: # both gpios timed out 101 | self.pi.set_watchdog(self.gpio_0, 0) 102 | self.pi.set_watchdog(self.gpio_1, 0) 103 | self.in_code = False 104 | self.callback(self.bits, self.num) 105 | 106 | def cancel(self): 107 | 108 | """ 109 | Cancel the Wiegand decoder. 110 | """ 111 | 112 | self.cb_0.cancel() 113 | self.cb_1.cancel() 114 | 115 | if __name__ == "__main__": 116 | 117 | import time 118 | 119 | import pigpio 120 | 121 | import wiegand 122 | 123 | def callback(bits, value): 124 | print("bits={} value={}".format(bits, value)) 125 | 126 | pi = pigpio.pi() 127 | 128 | w = wiegand.decoder(pi, 14, 15, callback) 129 | 130 | time.sleep(300) 131 | 132 | w.cancel() 133 | 134 | pi.stop() 135 | 136 | -------------------------------------------------------------------------------- /EXAMPLES/Shell/GPIOTEST/README: -------------------------------------------------------------------------------- 1 | This bash script tests the user gpios. 2 | 3 | Everything should be disconnected from the gpios. 4 | 5 | The pigpio daemon must be running (sudo pigpiod). 6 | 7 | Video at http://youtu.be/sCJFLKWaxHo 8 | -------------------------------------------------------------------------------- /EXAMPLES/Shell/GPIOTEST/gpiotest: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | skipped="" 4 | tested="" 5 | failed="" 6 | 7 | usage() 8 | { 9 | cat </dev/null 94 | 95 | usage 96 | 97 | v=$(pigs hwver) 98 | 99 | if [[ $v < 0 ]] 100 | then 101 | echo "The pigpio daemon wasn't found. Did you sudo pigpiod?" 102 | exit 103 | fi 104 | 105 | echo "Testing..." 106 | 107 | for ((i=0; i<4; i++)) do check_gpio $i 1; done 108 | for ((i=4; i<16; i++)) do check_gpio $i 0; done 109 | 110 | if [[ $v -ge 16 ]]; 111 | then 112 | check_gpio 16 0 113 | else 114 | skipped+="16 " 115 | fi 116 | 117 | for ((i=17; i<28; i++)) do check_gpio $i 0; done 118 | for ((i=28; i<30; i++)) do check_gpio $i 1; done 119 | for ((i=30; i<32; i++)) do check_gpio $i 0; done 120 | 121 | if [[ $failed = "" ]]; then failed="None"; fi 122 | 123 | echo "Skipped non-user gpios: $skipped" 124 | echo "Tested user gpios: $tested" 125 | echo "Failed user gpios: $failed" 126 | 127 | -------------------------------------------------------------------------------- /MakeRemote: -------------------------------------------------------------------------------- 1 | # 2 | CC = gcc 3 | SIZE = size 4 | SHLIB = gcc -shared 5 | STRIPLIB = strip --strip-unneeded 6 | 7 | CFLAGS += -O3 -Wall -pthread 8 | 9 | ALL = libpigpiod_if.so libpigpiod_if2.so pigs x_pigpiod_if x_pigpiod_if2 10 | 11 | prefix = /usr/local 12 | exec_prefix = $(prefix) 13 | bindir = $(exec_prefix)/bin 14 | includedir = $(prefix)/include 15 | libdir = $(prefix)/lib 16 | mandir = $(prefix)/man 17 | 18 | all: $(ALL) pigpio.py setup.py 19 | 20 | pigpiod_if.o: pigpiod_if.c pigpio.h command.h pigpiod_if.h 21 | $(CC) $(CFLAGS) -fpic -c -o pigpiod_if.o pigpiod_if.c 22 | 23 | pigpiod_if2.o: pigpiod_if2.c pigpio.h command.h pigpiod_if2.h 24 | $(CC) $(CFLAGS) -fpic -c -o pigpiod_if2.o pigpiod_if2.c 25 | 26 | command.o: command.c pigpio.h command.h 27 | $(CC) $(CFLAGS) -fpic -c -o command.o command.c 28 | 29 | pigs: command.o pigs.o 30 | $(CC) $(CFLAGS) -fpic -o pigs pigs.c command.c 31 | 32 | x_pigpiod_if: x_pigpiod_if.o $(LIB1) 33 | $(CC) -o x_pigpiod_if x_pigpiod_if.o $(LL1) 34 | 35 | x_pigpiod_if2: x_pigpiod_if2.o $(LIB2) 36 | $(CC) -o x_pigpiod_if2 x_pigpiod_if2.o $(LL2) 37 | 38 | clean: 39 | rm -f *.o *.i *.s *~ $(ALL) 40 | 41 | install: $(LIB1) $(LIB2) 42 | install -m 0755 -d $(DESTDIR)$(includedir) 43 | install -m 0644 pigpio.h $(DESTDIR)$(includedir) 44 | install -m 0644 pigpiod_if.h $(DESTDIR)$(includedir) 45 | install -m 0644 pigpiod_if2.h $(DESTDIR)$(includedir) 46 | install -m 0755 -d $(DESTDIR)$(libdir) 47 | install -m 0644 libpigpiod_if.so $(DESTDIR)$(libdir) 48 | install -m 0644 libpigpiod_if2.so $(DESTDIR)$(libdir) 49 | install -m 0755 -d $(DESTDIR)$(bindir) 50 | install -m 0755 pigs $(DESTDIR)$(bindir) 51 | python2 setup.py install 52 | python3 setup.py install 53 | install -m 0755 -d $(DESTDIR)$(mandir)/man1 54 | install -m 0644 *.1 $(DESTDIR)$(mandir)/man1 55 | install -m 0755 -d $(DESTDIR)$(mandir)/man3 56 | install -m 0644 *.3 $(DESTDIR)$(mandir)/man3 57 | 58 | uninstall: 59 | rm -f $(DESTDIR)$(includedir)/pigpio.h 60 | rm -f $(DESTDIR)$(includedir)/pigpiod_if.h 61 | rm -f $(DESTDIR)$(includedir)/pigpiod_if2.h 62 | rm -f $(DESTDIR)$(libdir)/libpigpiod_if.so 63 | rm -f $(DESTDIR)$(libdir)/libpigpiod_if2.so 64 | echo removing python2 files 65 | python2 setup.py install --record /tmp/pigpio >/dev/null 66 | xargs rm -f < /tmp/pigpio >/dev/null 67 | echo removing python3 files 68 | python3 setup.py install --record /tmp/pigpio >/dev/null 69 | xargs rm -f < /tmp/pigpio >/dev/null 70 | rm -f $(DESTDIR)$(bindir)/pigs 71 | rm -f $(DESTDIR)$(mandir)/man1/pig*.1 72 | rm -f $(DESTDIR)$(mandir)/man3/pig*.3 73 | 74 | LL1 = -L. -lpigpiod_if -pthread -lrt 75 | LL2 = -L. -lpigpiod_if2 -pthread -lrt 76 | 77 | LIB1 = libpigpiod_if.so 78 | OBJ1 = pigpiod_if.o command.o 79 | 80 | LIB2 = libpigpiod_if2.so 81 | OBJ2 = pigpiod_if2.o command.o 82 | 83 | $(LIB1): $(OBJ1) 84 | $(SHLIB) -o $(LIB1) $(OBJ1) 85 | $(STRIPLIB) $(LIB1) 86 | $(SIZE) $(LIB1) 87 | 88 | $(LIB2): $(OBJ2) 89 | $(SHLIB) -o $(LIB2) $(OBJ2) 90 | $(STRIPLIB) $(LIB2) 91 | $(SIZE) $(LIB2) 92 | 93 | # generated using gcc -MM *.c 94 | 95 | command.o: command.c pigpio.h command.h 96 | pigpiod.o: pigpiod.c pigpio.h 97 | pigpiod_if.o: pigpiod_if.c pigpio.h pigpiod_if.h command.h 98 | pigpiod_if2.o: pigpiod_if2.c pigpio.h pigpiod_if2.h command.h 99 | pigs.o: pigs.c pigpio.h command.h pigs.h 100 | 101 | 102 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # Set CROSS_PREFIX to prepend to all compiler tools at once for easier 3 | # cross-compilation. 4 | CROSS_PREFIX = 5 | CC = $(CROSS_PREFIX)gcc 6 | AR = $(CROSS_PREFIX)ar 7 | RANLIB = $(CROSS_PREFIX)ranlib 8 | SIZE = $(CROSS_PREFIX)size 9 | STRIP = $(CROSS_PREFIX)strip 10 | SHLIB = $(CC) -shared 11 | STRIPLIB = $(STRIP) --strip-unneeded 12 | 13 | SOVERSION = 1 14 | 15 | CFLAGS += -O3 -Wall -pthread 16 | 17 | LIB1 = libpigpio.so 18 | OBJ1 = pigpio.o command.o 19 | 20 | LIB2 = libpigpiod_if.so 21 | OBJ2 = pigpiod_if.o command.o 22 | 23 | LIB3 = libpigpiod_if2.so 24 | OBJ3 = pigpiod_if2.o command.o 25 | 26 | LIB = $(LIB1) $(LIB2) $(LIB3) 27 | 28 | ALL = $(LIB) x_pigpio x_pigpiod_if x_pigpiod_if2 pig2vcd pigpiod pigs 29 | 30 | LL1 = -L. -lpigpio -pthread -lrt 31 | 32 | LL2 = -L. -lpigpiod_if -pthread -lrt 33 | 34 | LL3 = -L. -lpigpiod_if2 -pthread -lrt 35 | 36 | prefix = /usr/local 37 | exec_prefix = $(prefix) 38 | bindir = $(exec_prefix)/bin 39 | includedir = $(prefix)/include 40 | libdir = $(prefix)/lib 41 | mandir = $(prefix)/man 42 | 43 | all: $(ALL) 44 | 45 | lib: $(LIB) 46 | 47 | pigpio.o: pigpio.c pigpio.h command.h custom.cext 48 | $(CC) $(CFLAGS) -fpic -c -o pigpio.o pigpio.c 49 | 50 | pigpiod_if.o: pigpiod_if.c pigpio.h command.h pigpiod_if.h 51 | $(CC) $(CFLAGS) -fpic -c -o pigpiod_if.o pigpiod_if.c 52 | 53 | pigpiod_if2.o: pigpiod_if2.c pigpio.h command.h pigpiod_if2.h 54 | $(CC) $(CFLAGS) -fpic -c -o pigpiod_if2.o pigpiod_if2.c 55 | 56 | command.o: command.c pigpio.h command.h 57 | $(CC) $(CFLAGS) -fpic -c -o command.o command.c 58 | 59 | x_pigpio: x_pigpio.o $(LIB1) 60 | $(CC) -o x_pigpio x_pigpio.o $(LL1) 61 | 62 | x_pigpiod_if: x_pigpiod_if.o $(LIB2) 63 | $(CC) -o x_pigpiod_if x_pigpiod_if.o $(LL2) 64 | 65 | x_pigpiod_if2: x_pigpiod_if2.o $(LIB3) 66 | $(CC) -o x_pigpiod_if2 x_pigpiod_if2.o $(LL3) 67 | 68 | pigpiod: pigpiod.o $(LIB1) 69 | $(CC) -o pigpiod pigpiod.o $(LL1) 70 | $(STRIP) pigpiod 71 | 72 | pigs: pigs.o command.o 73 | $(CC) -o pigs pigs.o command.o 74 | $(STRIP) pigs 75 | 76 | pig2vcd: pig2vcd.o 77 | $(CC) -o pig2vcd pig2vcd.o 78 | $(STRIP) pig2vcd 79 | 80 | clean: 81 | rm -f *.o *.i *.s *~ $(ALL) *.so.$(SOVERSION) 82 | 83 | ifeq ($(DESTDIR),) 84 | PYINSTALLARGS = 85 | else 86 | PYINSTALLARGS = --root=$(DESTDIR) 87 | endif 88 | 89 | install: $(ALL) 90 | install -m 0755 -d $(DESTDIR)/opt/pigpio/cgi 91 | install -m 0755 -d $(DESTDIR)$(includedir) 92 | install -m 0644 pigpio.h $(DESTDIR)$(includedir) 93 | install -m 0644 pigpiod_if.h $(DESTDIR)$(includedir) 94 | install -m 0644 pigpiod_if2.h $(DESTDIR)$(includedir) 95 | install -m 0755 -d $(DESTDIR)$(libdir) 96 | install -m 0755 libpigpio.so.$(SOVERSION) $(DESTDIR)$(libdir) 97 | install -m 0755 libpigpiod_if.so.$(SOVERSION) $(DESTDIR)$(libdir) 98 | install -m 0755 libpigpiod_if2.so.$(SOVERSION) $(DESTDIR)$(libdir) 99 | cd $(DESTDIR)$(libdir) && ln -fs libpigpio.so.$(SOVERSION) libpigpio.so 100 | cd $(DESTDIR)$(libdir) && ln -fs libpigpiod_if.so.$(SOVERSION) libpigpiod_if.so 101 | cd $(DESTDIR)$(libdir) && ln -fs libpigpiod_if2.so.$(SOVERSION) libpigpiod_if2.so 102 | install -m 0755 -d $(DESTDIR)$(bindir) 103 | install -m 0755 pig2vcd $(DESTDIR)$(bindir) 104 | install -m 0755 pigpiod $(DESTDIR)$(bindir) 105 | install -m 0755 pigs $(DESTDIR)$(bindir) 106 | if which python2; then python2 setup.py install $(PYINSTALLARGS); fi 107 | if which python3; then python3 setup.py install $(PYINSTALLARGS); fi 108 | install -m 0755 -d $(DESTDIR)$(mandir)/man1 109 | install -m 0644 p*.1 $(DESTDIR)$(mandir)/man1 110 | install -m 0755 -d $(DESTDIR)$(mandir)/man3 111 | install -m 0644 p*.3 $(DESTDIR)$(mandir)/man3 112 | ifeq ($(DESTDIR),) 113 | ldconfig 114 | endif 115 | 116 | uninstall: 117 | rm -f $(DESTDIR)$(includedir)/pigpio.h 118 | rm -f $(DESTDIR)$(includedir)/pigpiod_if.h 119 | rm -f $(DESTDIR)$(includedir)/pigpiod_if2.h 120 | rm -f $(DESTDIR)$(libdir)/libpigpio.so 121 | rm -f $(DESTDIR)$(libdir)/libpigpiod_if.so 122 | rm -f $(DESTDIR)$(libdir)/libpigpiod_if2.so 123 | rm -f $(DESTDIR)$(libdir)/libpigpio.so.$(SOVERSION) 124 | rm -f $(DESTDIR)$(libdir)/libpigpiod_if.so.$(SOVERSION) 125 | rm -f $(DESTDIR)$(libdir)/libpigpiod_if2.so.$(SOVERSION) 126 | rm -f $(DESTDIR)$(bindir)/pig2vcd 127 | rm -f $(DESTDIR)$(bindir)/pigpiod 128 | rm -f $(DESTDIR)$(bindir)/pigs 129 | if which python2; then python2 setup.py install $(PYINSTALLARGS) --record /tmp/pigpio >/dev/null; sed 's!^!$(DESTDIR)!' < /tmp/pigpio | xargs rm -f >/dev/null; fi 130 | if which python3; then python3 setup.py install $(PYINSTALLARGS) --record /tmp/pigpio >/dev/null; sed 's!^!$(DESTDIR)!' < /tmp/pigpio | xargs rm -f >/dev/null; fi 131 | rm -f $(DESTDIR)$(mandir)/man1/pig*.1 132 | rm -f $(DESTDIR)$(mandir)/man1/libpigpio*.1 133 | rm -f $(DESTDIR)$(mandir)/man3/pig*.3 134 | ifeq ($(DESTDIR),) 135 | ldconfig 136 | endif 137 | 138 | $(LIB1): $(OBJ1) 139 | $(SHLIB) -pthread -Wl,-soname,$(LIB1).$(SOVERSION) -o $(LIB1).$(SOVERSION) $(OBJ1) 140 | ln -fs $(LIB1).$(SOVERSION) $(LIB1) 141 | $(STRIPLIB) $(LIB1) 142 | $(SIZE) $(LIB1) 143 | 144 | $(LIB2): $(OBJ2) 145 | $(SHLIB) -pthread -Wl,-soname,$(LIB2).$(SOVERSION) -o $(LIB2).$(SOVERSION) $(OBJ2) 146 | ln -fs $(LIB2).$(SOVERSION) $(LIB2) 147 | $(STRIPLIB) $(LIB2) 148 | $(SIZE) $(LIB2) 149 | 150 | $(LIB3): $(OBJ3) 151 | $(SHLIB) -pthread -Wl,-soname,$(LIB3).$(SOVERSION) -o $(LIB3).$(SOVERSION) $(OBJ3) 152 | ln -fs $(LIB3).$(SOVERSION) $(LIB3) 153 | $(STRIPLIB) $(LIB3) 154 | $(SIZE) $(LIB3) 155 | 156 | # generated using gcc -MM *.c 157 | 158 | pig2vcd.o: pig2vcd.c pigpio.h 159 | pigpiod.o: pigpiod.c pigpio.h 160 | pigs.o: pigs.c pigpio.h command.h pigs.h 161 | x_pigpio.o: x_pigpio.c pigpio.h 162 | x_pigpiod_if.o: x_pigpiod_if.c pigpiod_if.h pigpio.h 163 | x_pigpiod_if2.o: x_pigpiod_if2.c pigpiod_if2.h pigpio.h 164 | 165 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | NOTE 2 | 3 | The initial part of the make, the compilation of pigpio.c, 4 | takes 100 seconds on early model Pis. Be patient. The overall 5 | install takes just over 3 minutes. 6 | 7 | INSTALL 8 | 9 | Extract the archive to a directory. 10 | 11 | IN THAT DIRECTORY 12 | 13 | Enter the following two commands (in this order) 14 | 15 | make 16 | sudo make install 17 | 18 | This will install 19 | 20 | o the library (libpigpio.so) in /usr/local/lib 21 | o the library (libpigpiod_if.so) in /usr/local/lib 22 | o the library (libpigpiod_if2.so) in /usr/local/lib 23 | o the header file (pigpio.h) in /usr/local/include 24 | o the header file (pigpiod_if.h) in /usr/local/include 25 | o the header file (pigpiod_if2.h) in /usr/local/include 26 | o the header file (pigs.h) in /usr/local/include 27 | o the daemon (pigpiod) in /usr/local/bin 28 | o the socket interface (pigs) in /usr/local/bin 29 | o the utility pig2vcd in /usr/local/bin 30 | o man pages in /usr/local/man/man1 and /usr/local/man/man3 31 | o the Python module pigpio.py for Python 2 and 3 32 | 33 | TEST (optional) 34 | 35 | *** WARNING ************************************************ 36 | * * 37 | * All the tests make extensive use of gpio 25 (pin 22). * 38 | * Ensure that either nothing or just a LED is connected to * 39 | * gpio 25 before running any of the tests. * 40 | * * 41 | * Some tests are statistical in nature and so may on * 42 | * occasion fail. Repeated failures on the same test or * 43 | * many failures in a group of tests indicate a problem. * 44 | ************************************************************ 45 | 46 | To test the library do 47 | 48 | sudo ./x_pigpio 49 | 50 | To test the pigpio daemon do 51 | 52 | sudo pigpiod 53 | 54 | ./x_pigpiod_if # test the C I/F to the pigpio daemon 55 | ./x_pigpiod_if2 # test the C I/F to the pigpio daemon 56 | ./x_pigpio.py # test the Python I/F to the pigpio daemon 57 | ./x_pigs # test the socket I/F to the pigpio daemon 58 | ./x_pipe # test the pipe I/F to the pigpio daemon 59 | 60 | EXAMPLE CODE 61 | 62 | x_pigpio.c, pig2vcd.c, and pigpiod.c show examples of interfacing 63 | with the pigpio library. 64 | 65 | pigs.c, pigpio.py, x_pigpiod_if, x_pigpiod_if2.c, x_pigpio.py, 66 | x_pigs, and x_pipe show examples of interfacing with the pigpio 67 | daemon. x_pipe uses the pipe interface, the others use the 68 | socket interface. 69 | 70 | DAEMON 71 | 72 | To launch the daemon do 73 | 74 | sudo pigpiod (pigpiod -? for options) 75 | 76 | Once the daemon is launched the socket and pipe interfaces will be 77 | available. 78 | 79 | When the library starts it locks 80 | 81 | /var/run/pigpio.pid 82 | 83 | The file should be automatically deleted when the library terminates. 84 | 85 | SOCKET INTERFACE 86 | 87 | Use pigs for the socket interface (pigs help for help). 88 | 89 | PIPE INTERFACE 90 | 91 | The pipe interface accepts commands written to /dev/pigpio. 92 | 93 | Results are read from /dev/pigout. 94 | 95 | Errors are output on /dev/pigerr. 96 | 97 | To test the pipe interface perhaps do 98 | 99 | cat /dev/pigout & 100 | cat /dev/pigerr & 101 | 102 | echo "help" >/dev/pigpio 103 | 104 | PYTHON MODULE 105 | 106 | The Python pigpio module is installed to the default Python location 107 | for Python 2 and Python 3. 108 | 109 | You can install it for additional Python versions by 110 | 111 | pythonx.y setup.py install 112 | 113 | where x.y is the Python version. 114 | 115 | STOP DAEMON 116 | 117 | To stop the pigpiod daemon 118 | 119 | sudo killall pigpiod 120 | 121 | RUNNING ON NON Pi's 122 | 123 | You can access the pigpiod daemon running on the Pi from any machine which 124 | is connected to it over the network. This access is via the socket interface. 125 | 126 | In particular this allows you to use the following on non-Pi's. 127 | 128 | o pigs 129 | o the pigpio Python module 130 | o the C socket I/F using libpigpiod_if (header file pigpiod_if.h) 131 | o the C socket I/F using libpigpiod_if2 (header file pigpiod_if2.h) 132 | 133 | On a Linux machine 134 | 135 | make -f MakeRemote clean 136 | make -f MakeRemote 137 | make -f MakeRemote install 138 | 139 | This will install 140 | 141 | o the library (libpigpiod_if.so) in /usr/local/lib 142 | o the library (libpigpiod_if2.so) in /usr/local/lib 143 | o the header file (pigpio.h) in /usr/local/include 144 | o the header file (pigpiod_if.h) in /usr/local/include 145 | o the header file (pigpiod_if2.h) in /usr/local/include 146 | o the socket interface (pigs) in /usr/local/bin 147 | o man pages in /usr/local/man/man1 and /usr/local/man/man3 148 | o the Python module pigpio.py 149 | 150 | On Windows machines (and possibly Macs) 151 | 152 | The Python module should install with 153 | 154 | python setup.py install 155 | 156 | pigs, pigpiod_if, and pigpiod_if2 will need minor mods to 157 | reflect the Windows/Mac socket interface. 158 | 159 | DOCUMENTATION 160 | 161 | The most up to date should be http://abyz.me.uk/rpi/pigpio/ 162 | 163 | On the Pi try 164 | 165 | man pigs 166 | man pigpiod 167 | man pig2vcd 168 | 169 | man pigpio 170 | man pigpiod_if 171 | man pigpiod_if2 172 | 173 | pydoc pigpio 174 | 175 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # pigpio 2 | 3 | pigpio is a C library for the Raspberry which allows control of the 4 | General Purpose Input Outputs (GPIO). 5 | 6 | ## Features 7 | 8 | * Sampling and time-stamping of GPIO 0-31 between 100,000 and 1,000,000 times per second 9 | * Provision of PWM on any number of the user GPIO simultaneously 10 | * Provision of servo pulses on any number of the user GPIO simultaneously 11 | * Callbacks when any of GPIO 0-31 change state (callbacks receive the time of the event 12 | accurate to a few microseconds) 13 | * Notifications via pipe when any of GPIO 0-31 change state 14 | * Callbacks at timed intervals 15 | * Reading/writing all of the GPIO in a bank (0-31, 32-53) as a single operation 16 | * Individually setting GPIO modes, reading and writing 17 | * Socket and pipe interfaces for the bulk of the functionality in addition to the 18 | underlying C library calls 19 | * Construction of arbitrary waveforms to give precise timing of output GPIO 20 | level changes (accurate to a few microseconds) 21 | * Software serial links, I2C, and SPI using any user GPIO 22 | * Rudimentary permission control through the socket and pipe interfaces so users 23 | can be prevented from "updating" inappropriate GPIO 24 | * Creating and running scripts on the pigpio daemon 25 | 26 | ## Interfaces 27 | 28 | The library provides a number of control interfaces 29 | * the C function interface, 30 | * the /dev/pigpio pipe interface, 31 | * the socket interface (used by the pigs utility and the Python module). 32 | 33 | ## Utilities 34 | 35 | A number of utility programs are provided: 36 | * the pigpiod daemon, 37 | * the Python module, 38 | * the piscope digital waveform viewer, 39 | * the pigs command line utility, 40 | * the pig2vcd utility which converts notifications into the value change dump (VCD) 41 | format (useful for viewing digital waveforms with GTKWave). 42 | 43 | ## Documentation 44 | 45 | See http://abyz.me.uk/rpi/pigpio/ 46 | 47 | ## Example programs 48 | 49 | See http://abyz.me.uk/rpi/pigpio/examples.html 50 | 51 | ## GPIO 52 | 53 | ALL GPIO are identified by their Broadcom number. See http://elinux.org. 54 | 55 | There are 54 GPIO in total, arranged in two banks. 56 | 57 | Bank 1 contains GPIO 0-31. Bank 2 contains GPIO 32-54. 58 | 59 | A user should only manipulate GPIO in bank 1. 60 | 61 | There are at least three types of board: 62 | * Type 1 63 | * 26 pin header (P1) 64 | * Hardware revision numbers of 2 and 3 65 | * User GPIO 0-1, 4, 7-11, 14-15, 17-18, 21-25 66 | * Type 2 67 | * 26 pin header (P1) and an additional 8 pin header (P5) 68 | * Hardware revision numbers of 4, 5, 6, and 15 69 | * User GPIO 2-4, 7-11, 14-15, 17-18, 22-25, 27-31 70 | * Type 3 71 | * 40 pin expansion header (J8) 72 | * Hardware revision numbers of 16 or greater 73 | * User GPIO 2-27 (0 and 1 are reserved) 74 | 75 | It is safe to read all the GPIO. If you try to write a system GPIO or change 76 | its mode you can crash the Pi or corrupt the data on the SD card. 77 | -------------------------------------------------------------------------------- /SUPPORT.md: -------------------------------------------------------------------------------- 1 | Questions about the pigpio library are welcome but we ask that you check these resources first: 2 | * [pigpio library web page](http://abyz.me.uk/rpi/pigpio) 3 | Noobs should start with the FAQ. All 4 | APIs are documented extensively. 5 | * Search the repository issues with a 'question' label 6 | For example, to search for information on PWM type in search box: 7 | `label:question pwm` 8 | * Check the repository's Wiki - WIP, help wanted. 9 | -------------------------------------------------------------------------------- /UNLICENCE: -------------------------------------------------------------------------------- 1 | This is free and unencumbered software released into the public domain. 2 | 3 | Anyone is free to copy, modify, publish, use, compile, sell, or 4 | distribute this software, either in source code form or as a compiled 5 | binary, for any purpose, commercial or non-commercial, and by any 6 | means. 7 | 8 | In jurisdictions that recognize copyright laws, the author or authors 9 | of this software dedicate any and all copyright interest in the 10 | software to the public domain. We make this dedication for the benefit 11 | of the public at large and to the detriment of our heirs and 12 | successors. We intend this dedication to be an overt act of 13 | relinquishment in perpetuity of all present and future rights to this 14 | software under copyright law. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | For more information, please refer to 25 | 26 | -------------------------------------------------------------------------------- /cmake/FindRT.cmake: -------------------------------------------------------------------------------- 1 | # FindRT.cmake - Try to find the RT library 2 | # Once done this will define 3 | # 4 | # RT_FOUND - System has rt 5 | # RT_INCLUDE_DIR - The rt include directory 6 | # RT_LIBRARIES - The libraries needed to use rt 7 | # RT_DEFINITIONS - Compiler switches required for using rt 8 | # 9 | # Also creates an import target called RT::RT 10 | 11 | find_path (RT_INCLUDE_DIR NAMES time.h 12 | PATHS 13 | /usr 14 | /usr/local 15 | /opt 16 | PATH_SUFFIXES 17 | ) 18 | 19 | find_library(RT_LIBRARIES NAMES rt 20 | PATHS 21 | /usr 22 | /usr/local 23 | /opt 24 | ) 25 | 26 | include(FindPackageHandleStandardArgs) 27 | 28 | FIND_PACKAGE_HANDLE_STANDARD_ARGS(rt DEFAULT_MSG RT_LIBRARIES RT_INCLUDE_DIR) 29 | 30 | mark_as_advanced(RT_INCLUDE_DIR RT_LIBRARIES) 31 | 32 | if (NOT TARGET RT::RT) 33 | add_library(RT::RT INTERFACE IMPORTED) 34 | 35 | set_target_properties(RT::RT PROPERTIES 36 | INTERFACE_INCLUDE_DIRECTORIES ${RT_INCLUDE_DIR} 37 | INTERFACE_LINK_LIBRARIES ${RT_LIBRARIES} 38 | ) 39 | endif() -------------------------------------------------------------------------------- /cmake/pigpioConfig.cmake: -------------------------------------------------------------------------------- 1 | include (${CMAKE_CURRENT_LIST_DIR}/pigpioTargets.cmake) -------------------------------------------------------------------------------- /cmake/setup.py.in: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | from distutils.core import setup 4 | 5 | setup(name='pigpio', 6 | version='1.44', 7 | author='joan', 8 | author_email='joan@abyz.me.uk', 9 | maintainer='joan', 10 | maintainer_email='joan@abyz.me.uk', 11 | url='http://abyz.me.uk/rpi/pigpio/python.html', 12 | description='Raspberry Pi GPIO module', 13 | long_description='Raspberry Pi Python module to access the pigpio daemon', 14 | download_url='http://abyz.me.uk/rpi/pigpio/pigpio.zip', 15 | license='unlicense.org', 16 | py_modules=['pigpio'], 17 | keywords=['raspberrypi', 'gpio',], 18 | classifiers=[ 19 | "Programming Language :: Python :: 2", 20 | "Programming Language :: Python :: 3", 21 | ], 22 | package_dir={ '': '${CMAKE_CURRENT_SOURCE_DIR}'} 23 | ) 24 | 25 | -------------------------------------------------------------------------------- /command.h: -------------------------------------------------------------------------------- 1 | /* 2 | This is free and unencumbered software released into the public domain. 3 | 4 | Anyone is free to copy, modify, publish, use, compile, sell, or 5 | distribute this software, either in source code form or as a compiled 6 | binary, for any purpose, commercial or non-commercial, and by any 7 | means. 8 | 9 | In jurisdictions that recognize copyright laws, the author or authors 10 | of this software dedicate any and all copyright interest in the 11 | software to the public domain. We make this dedication for the benefit 12 | of the public at large and to the detriment of our heirs and 13 | successors. We intend this dedication to be an overt act of 14 | relinquishment in perpetuity of all present and future rights to this 15 | software under copyright law. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 21 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 22 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23 | OTHER DEALINGS IN THE SOFTWARE. 24 | 25 | For more information, please refer to 26 | */ 27 | 28 | /* 29 | This version is for pigpio version 70+ 30 | */ 31 | 32 | #ifndef COMMAND_H 33 | #define COMMAND_H 34 | 35 | #include 36 | #include 37 | 38 | #include "pigpio.h" 39 | 40 | #define CMD_MAX_PARAM 512 41 | #define CMD_MAX_EXTENSION (1<<16) 42 | 43 | #define CMD_UNKNOWN_CMD -1 44 | #define CMD_BAD_PARAMETER -2 45 | #define CMD_EXT_TOO_SMALL -3 46 | #define CMD_NOT_IN_SCRIPT -4 47 | 48 | #define CMD_P_ARR 10 49 | #define CMD_V_ARR 10 50 | 51 | #define CMD_NUMERIC 1 52 | #define CMD_VAR 2 53 | #define CMD_PAR 3 54 | 55 | typedef struct 56 | { 57 | uint32_t cmd; 58 | uint32_t p1; 59 | uint32_t p2; 60 | union 61 | { 62 | uint32_t p3; 63 | uint32_t ext_len; 64 | uint32_t res; 65 | }; 66 | } cmdCmd_t; 67 | 68 | typedef struct 69 | { 70 | int eaten; 71 | int8_t opt[4]; 72 | } cmdCtlParse_t; 73 | 74 | typedef struct 75 | { 76 | int cmd; /* command number */ 77 | char *name; /* command name */ 78 | int vt; /* command verification type */ 79 | int rv; /* command return value type */ 80 | int cvis; /* command valid in a script */ 81 | } cmdInfo_t; 82 | 83 | typedef struct 84 | { 85 | uint32_t tag; 86 | int step; 87 | } cmdTagStep_t; 88 | 89 | typedef struct 90 | { 91 | uintptr_t p[5]; //these are sometimes converted to pointers, so presumablly they sometimes have pointers stored in them, I haven't figured out where though. --plugwash 92 | int8_t opt[4]; 93 | } cmdInstr_t; 94 | 95 | typedef struct 96 | { 97 | /* 98 | +-----------+---------+---------+----------------+ 99 | | PARAMS... | VARS... | CMDS... | STRING AREA... | 100 | +-----------+---------+---------+----------------+ 101 | */ 102 | int *par; 103 | int *var; 104 | cmdInstr_t *instr; 105 | int instrs; 106 | char *str_area; 107 | int str_area_len; 108 | int str_area_pos; 109 | } cmdScript_t; 110 | 111 | extern cmdInfo_t cmdInfo[]; 112 | 113 | extern char *cmdUsage; 114 | 115 | int cmdParse(char *buf, uintptr_t *p, unsigned ext_len, char *ext, cmdCtlParse_t *ctl); 116 | 117 | int cmdParseScript(char *script, cmdScript_t *s, int diags); 118 | 119 | char *cmdErrStr(int error); 120 | 121 | char *cmdStr(void); 122 | 123 | #endif 124 | 125 | -------------------------------------------------------------------------------- /custom.cext: -------------------------------------------------------------------------------- 1 | /* 2 | This version is for pigpio version 26+ 3 | 4 | If you want customised functions replace this file with your own 5 | definitions for gpioCustom1 and gpioCustom2. 6 | */ 7 | 8 | #include "pigpio.h" 9 | 10 | int gpioCustom1(unsigned arg1, unsigned arg2, char *argx, unsigned count) 11 | { 12 | int i; 13 | unsigned max; 14 | 15 | DBG(DBG_USER, "arg1=%d arg2=%d count=%d [%s]", 16 | arg1, arg2, count, myBuf2Str(count, argx)); 17 | 18 | CHECK_INITED; 19 | 20 | /* for dummy just return max parameter */ 21 | 22 | if (arg1 > arg2) max = arg1; else max = arg2; 23 | 24 | for (i=0; i max) max = argx[i]; 25 | 26 | return max; 27 | } 28 | 29 | 30 | int gpioCustom2(unsigned arg1, char *argx, unsigned count, 31 | char *retBuf, unsigned retMax) 32 | { 33 | int i, j, t; 34 | 35 | DBG(DBG_USER, "arg1=%d count=%d [%s] retMax=%d", 36 | arg1, count, myBuf2Str(count, argx), retMax); 37 | 38 | CHECK_INITED; 39 | 40 | /* for dummy just return argx reversed */ 41 | 42 | if (count > retMax) count = retMax; 43 | 44 | for (i=0, j=count-1; i<=j; i++, j--) 45 | { 46 | /* t used as argx and retBuf may be the same buffer */ 47 | t = argx[i]; 48 | retBuf[i] = argx[j]; 49 | retBuf[j] = t; 50 | } 51 | 52 | return count; 53 | } 54 | 55 | -------------------------------------------------------------------------------- /pig2vcd.1: -------------------------------------------------------------------------------- 1 | 2 | ." Process this file with 3 | ." groff -man -Tascii pig2vcd.1 4 | ." 5 | .TH pig2vcd 1 2012-2020 Linux "pigpio archive" 6 | .SH NAME 7 | pig2vd - A utility to convert pigpio notifications to VCD. 8 | 9 | .SH SYNOPSIS 10 | 11 | pig2vcd file.VCD 12 | .SH DESCRIPTION 13 | 14 | 15 | .ad l 16 | 17 | .nh 18 | pig2vcd is a utility which reads notifications on stdin and writes the 19 | output as a Value Change Dump (VCD) file on stdout. 20 | 21 | .br 22 | 23 | .br 24 | The VCD file can be viewed using GTKWave. 25 | 26 | .br 27 | 28 | .br 29 | .SS Notifications 30 | .br 31 | 32 | .br 33 | Notifications consist of 12 bytes with the following binary format. 34 | 35 | .br 36 | 37 | .br 38 | 39 | .EX 40 | typedef struct 41 | .br 42 | { 43 | .br 44 | uint16_t seqno; 45 | .br 46 | uint16_t flags; 47 | .br 48 | uint32_t tick; 49 | .br 50 | uint32_t level; 51 | .br 52 | } gpioReport_t; 53 | .br 54 | 55 | .EE 56 | 57 | .br 58 | 59 | .br 60 | seqno: starts at 0 each time the handle is opened and then increments by one for each report. 61 | 62 | .br 63 | 64 | .br 65 | flags: two flags are defined, PI_NTFY_FLAGS_WDOG and PI_NTFY_FLAGS_ALIVE. If bit 5 is set (PI_NTFY_FLAGS_WDOG) then bits 0-4 of the flags indicate a gpio which has had a watchdog timeout; if bit 6 is set (PI_NTFY_FLAGS_ALIVE) this indicates a keep alive signal on the pipe/socket and is sent once a minute in the absence of other notification activity. 66 | 67 | .br 68 | 69 | .br 70 | tick: the number of microseconds since system boot. It wraps around after 1h12m. 71 | 72 | .br 73 | 74 | .br 75 | level: indicates the level of each gpio. If bit 1< 26 | */ 27 | 28 | /* 29 | This version is for pigpio version 3+ 30 | */ 31 | 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | 42 | #include "pigpio.h" 43 | 44 | /* 45 | This software converts pigpio notification reports 46 | into a VCD format understood by GTKWave. 47 | */ 48 | 49 | #define RS (sizeof(gpioReport_t)) 50 | 51 | static char * timeStamp() 52 | { 53 | static char buf[32]; 54 | 55 | struct timeval now; 56 | struct tm tmp; 57 | 58 | gettimeofday(&now, NULL); 59 | 60 | localtime_r(&now.tv_sec, &tmp); 61 | strftime(buf, sizeof(buf), "%F %T", &tmp); 62 | 63 | return buf; 64 | } 65 | 66 | int symbol(int bit) 67 | { 68 | if (bit < 26) return ('A' + bit); 69 | else return ('a' + bit - 26); 70 | } 71 | 72 | int main(int argc, char * argv[]) 73 | { 74 | int b, r, v; 75 | uint32_t t0; 76 | uint32_t lastLevel, changed; 77 | 78 | gpioReport_t report; 79 | 80 | r=read(STDIN_FILENO, &report, RS); 81 | 82 | if (r != RS) exit(-1); 83 | 84 | printf("$date %s $end\n", timeStamp()); 85 | printf("$version pig2vcd V1 $end\n"); 86 | printf("$timescale 1 us $end\n"); 87 | printf("$scope module top $end\n"); 88 | 89 | for (b=0; b<32; b++) 90 | printf("$var wire 1 %c %d $end\n", symbol(b), b); 91 | 92 | printf("$upscope $end\n"); 93 | printf("$enddefinitions $end\n"); 94 | 95 | t0 = report.tick; 96 | lastLevel =0; 97 | 98 | while ((r=read(STDIN_FILENO, &report, RS)) == RS) 99 | { 100 | if (report.level != lastLevel) 101 | { 102 | printf("#%u\n", report.tick - t0); 103 | 104 | changed = report.level ^ lastLevel; 105 | 106 | lastLevel = report.level; 107 | 108 | for (b=0; b<32; b++) 109 | { 110 | if (changed & (1< 26 | */ 27 | 28 | /* 29 | This version is for pigpio version 67+ 30 | */ 31 | 32 | #ifndef PIGS_H 33 | #define PIGS_H 34 | 35 | #define PIGS_OK 0 36 | #define PIGS_CONNECT_ERR 255 37 | #define PIGS_OPTION_ERR 254 38 | #define PIGS_SCRIPT_ERR 253 39 | 40 | #endif 41 | 42 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | from distutils.core import setup 4 | 5 | setup(name='pigpio', 6 | version='1.78', 7 | author='joan', 8 | author_email='joan@abyz.me.uk', 9 | maintainer='joan', 10 | maintainer_email='joan@abyz.me.uk', 11 | url='http://abyz.me.uk/rpi/pigpio/python.html', 12 | description='Raspberry Pi GPIO module', 13 | long_description='Raspberry Pi Python module to access the pigpio daemon', 14 | download_url='http://abyz.me.uk/rpi/pigpio/pigpio.zip', 15 | license='unlicense.org', 16 | py_modules=['pigpio'], 17 | keywords=['raspberrypi', 'gpio',], 18 | classifiers=[ 19 | "Programming Language :: Python :: 2", 20 | "Programming Language :: Python :: 3", 21 | ] 22 | ) 23 | 24 | -------------------------------------------------------------------------------- /util/Findpigpio.cmake: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | ### Find the pigpio shared libraries. 3 | ################################################################################ 4 | 5 | # Find the path to the pigpio includes. 6 | find_path(pigpio_INCLUDE_DIR 7 | NAMES pigpio.h pigpiod_if.h pigpiod_if2.h 8 | HINTS /usr/local/include) 9 | 10 | # Find the pigpio libraries. 11 | find_library(pigpio_LIBRARY 12 | NAMES libpigpio.so 13 | HINTS /usr/local/lib) 14 | find_library(pigpiod_if_LIBRARY 15 | NAMES libpigpiod_if.so 16 | HINTS /usr/local/lib) 17 | find_library(pigpiod_if2_LIBRARY 18 | NAMES libpigpiod_if2.so 19 | HINTS /usr/local/lib) 20 | 21 | # Set the pigpio variables to plural form to make them accessible for 22 | # the paramount cmake modules. 23 | set(pigpio_INCLUDE_DIRS ${pigpio_INCLUDE_DIR}) 24 | set(pigpio_INCLUDES ${pigpio_INCLUDE_DIR}) 25 | 26 | # Handle REQUIRED, QUIET, and version arguments 27 | # and set the _FOUND variable. 28 | include(FindPackageHandleStandardArgs) 29 | find_package_handle_standard_args(pigpio 30 | DEFAULT_MSG 31 | pigpio_INCLUDE_DIR pigpio_LIBRARY pigpiod_if_LIBRARY pigpiod_if2_LIBRARY) 32 | -------------------------------------------------------------------------------- /util/pigpiod.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Pigpio daemon 3 | 4 | [Service] 5 | Type=forking 6 | PIDFile=pigpio.pid 7 | ExecStart=/usr/bin/pigpiod 8 | 9 | [Install] 10 | WantedBy=multi-user.target 11 | -------------------------------------------------------------------------------- /util/readme.md: -------------------------------------------------------------------------------- 1 | This folder provides utility files for the pigpio library. 2 | 3 | ### pigpiod 4 | 5 | `pigpiod` is a script that allows to run pigpiod as a Linux service with root privileges. 6 | The advantage of running pigpiod as a service is that pigpiod can be automatically launched on system startup. 7 | To automatically start pigpiod as a service, do the following: 8 | 9 | + Copy `pigpiod` from this directory to `/etc/init.d/`. 10 | 11 | + Make it executable: 12 | ``` 13 | sudo chmod +x /etc/init.d/pigpiod 14 | ``` 15 | 16 | + Tell update-rc.d to automatically start the pigpiod service on system startup: 17 | ``` 18 | sudo update-rc.d pigpiod defaults 19 | ``` 20 | 21 | + Now, you can start, stop, and restart pigpiod using 22 | ``` 23 | sudo service pigpiod start 24 | sudo service pigpiod stop 25 | sudo service pigpiod restart 26 | ``` 27 | 28 | 29 | ### Findpigpio.cmake 30 | 31 | `Findpigpio.cmake` is a script used by CMake to find out where the pigpio header and library files are located. 32 | --------------------------------------------------------------------------------