diff --git a/README.md b/README.md index 9431a92..0713297 100644 --- a/README.md +++ b/README.md @@ -1,68 +1,277 @@ -### Note +Raspberry Pi Low Level IO +========================= -This is an unofficial port of Gordon's WiringPi library. Please do not email Gordon if you have issues, he will not be able to help. +# Installation +``` +pip install wiringpi +``` -For support, comments, questions, etc please join the WiringPi Discord channel: https://discord.gg/SM4WUVG +# API -# WiringPi for Python +## Root Namespace -WiringPi: An implementation of most of the Arduino Wiring functions for the Raspberry Pi. +The raspi-llio module consists of four namespaces, GPIO, I2C, PWM, and a single method ```getBoardRev```: -WiringPi implements new functions for managing IO expanders. +### getBoardRev -# Quick Install +The ```getBoardRev``` method takes no parameters and returns either 1 or 2, indicating if this is a Raspberry Pi Model B +rev 1 or 2. -`pip install wiringpi` +## GPIO -# Usage +Using GPIO is straightforward, just create an instance of a pin and call ```digitalWrite``` or ```digitalRead```: -```python -import wiringpi +```javascript +var raspi = require('raspi-llio'); -# One of the following MUST be called before using IO functions: -wiringpi.wiringPiSetup() # For sequential pin numbering -# OR -wiringpi.wiringPiSetupSys() # For /sys/class/gpio with GPIO pin numbering -# OR -wiringpi.wiringPiSetupGpio() # For GPIO pin numbering +var pin7 = new raspi.GPIO(7, raspi.GPIO.OUTPUT); +var pin11 = new raspi.GPIO(11, raspi.GPIO.INPUT); + +console.log(pin11.digitalRead() == raspi.GPIO.LOW); // Prints true +pin7.digitalWrite(raspi.GPIO.HIGH); +console.log(pin11.digitalRead() == raspi.GPIO.HIGH); // Prints true ``` -**General IO:** +### new _constructor_(pin, mode, [pullUpDown]) -```python -wiringpi.pinMode(6, 1) # Set pin 6 to 1 ( OUTPUT ) -wiringpi.digitalWrite(6, 1) # Write 1 ( HIGH ) to pin 6 -wiringpi.digitalRead(6) # Read pin 6 +Instantiates a new GPIO pin instance. + +#### Parameters: + +- pin (_number_) + - The pin number, as numbered on the P1 header +- mode (```raspi.GPIO.INPUT, raspi.GPIO.OUTPUT```) + - The mode for the pin +- pullUpDown (```raspi.GPIO.PUD_OFF, raspi.GPIO.PUD_DOWN, raspi.GPIO.PUD_UP```) Optional. + - Enables a pull up or pull down resistor on the pin + +## GPIO Instances + +### value digitalRead() + +Reads the value on the pin and returns either ```raspi.GPIO.LOW``` or ```raspi.GPIO.HIGH```. Only valid when the pin mode +is ```INPUT```. + +### digitalWrite(value) + +The digital write method takes one parameter, either ```raspi.GPIO.LOW``` or ```raspi.GPIO.HIGH``` and sets the pin value. +Only valid when the pin mode is ```OUTPUT``` + +## PWM + +Generating a PWM output works like GPIO; you first instantiate a PWM instance and then call ```pwmWrite```. To control a servo: + +```javascript +var raspi = require('raspi-llio'); + +var pwm = new raspi.PWM(); +raspi.PWM.setMode(0); +raspi.PWM.setClockDivisor(400); +raspi.PWM.setRange(1000); + +var value = 40; +setInterval(function() { + if (value == 40) { + value = 90; + } else { + value = 40; + } + pwm.write(value); +}, 2000); ``` -**Setting up a peripheral:** +**Important**: If you are driving a servo, the value should be between about 40 and 90 for 90 degree servos, and 20 and 110 for 180 +degree servos. Make sure to test these values with your specific servo and make sure you aren't overdriving your servo, +as this can also harm your Raspberry Pi. Also make sure that you have a good power supply because the 5V power +on the Raspberry Pi is notoriously fickle. If you see that your Raspberry Pi is being reset when trying to drive a sero, +you will need to either get a better power supply for your Raspberry Pi, or you will need to power the servo using an +external source. -WiringPi supports expanding your range of available "pins" by setting up a port expander. The implementation details of -your port expander will be handled transparently, and you can write to the additional pins (starting from PIN_OFFSET >= 64) -as if they were normal pins on the Pi. +### new _constructor_() -```python -wiringpi.mcp23017Setup(PIN_OFFSET, I2C_ADDR) +Instantiates a new PWM channel instance. + +### setMode(mode) + +Sets the PWM mode, must be one of ```raspi.PWM.PWM_MODE_MS``` or ```raspi.PWM.PWM_MODE_BAL```. See the [BCM2835 ARM Peripherals datasheet](http://www.raspberrypi.org/wp-content/uploads/2012/02/BCM2835-ARM-Peripherals.pdf) +for more information. + +### setRange(range) + +Sets the value of the PWM range register. See the [BCM2835 ARM Peripherals datasheet](http://www.raspberrypi.org/wp-content/uploads/2012/02/BCM2835-ARM-Peripherals.pdf) +for more information. + +### setClockDivisor(divisor) + +Sets the PWM clock divisor. See the [BCM2835 ARM Peripherals datasheet](http://www.raspberrypi.org/wp-content/uploads/2012/02/BCM2835-ARM-Peripherals.pdf) +for more information. + +## PWM Instances + +### write(value) + +Sets the PWM duty cycle to ```value / 1000```, assuming the default clock divisor and range. The value should be between +0 and the max PWM value. The max PWM value is set by ```raspi.PWM.setPwmRange()``` and defaults to 1024. + +## I2C + +Interfacing with I2C devices requires instantiating a new instance that represents an external device attached via I2C: + +```javascript +var raspi = require('raspi-llio'); + +var sensor = new raspi.I2C(0x18); + +setInterval(function(){ + console.log(sensor.readReg16(5)); +}, 500); ``` -This example was tested on a quick2wire board with one digital IO expansion board connected via I2C: +Some I2C devices work by being read from/written to directly. In these cases, use the ```read``` and ```write``` methods. +Most devices are register based, however, so use the ```readRegX``` and ```writeRegX``` methods. Consult the data sheets +for the I2C device to determine which method is appropriate. -```python -wiringpi.mcp23017Setup(65, 0x20) -wiringpi.pinMode(65, 1) -wiringpi.digitalWrite(65, 1) +**Note:** If you encounter a "No such file or directory" error when trying to use I2C peripherals, you may need to load the I2C driver from the command line with: + +``` +gpio load i2c ``` -**Soft Tone:** +### new _constructor_(address) -Hook a speaker up to your Pi and generate music with softTone. Also useful for generating frequencies for other uses such as modulating A/C. +Instantiates a new I2C peripheral instance that corresponds to the device at the given address. + +## I2C Instances + +### data read() + +Reads some data from the I2C peripheral. Blocks if there is nothing to read until something can be read. + +### write(data) + +Writes some data to the I2C peripheral. + +### writeReg8(register, data) + +Writes some data to an 8-bit register in the I2C peripheral. + +### writeReg16(register, data) + +Writes some data to a 16-bit register in the I2C peripheral. + +### data readReg8(register) + +Reads some data from an 8-bit register in the I2C peripheral. + +### data readReg16(register) + +Reads some data from a 16-bit register in the I2C peripheral. + +## SPI + +Interfacing with an SPI device requires instantiating an SPI instance representing an SPI channel at a certain speed: + +```javascript +var raspi = require('raspi-llio'); + +var spi = new raspi.SPI(0, 1000000); // Creates an SPI on channel 0 running at 1Mbps +spi.readWrite('Hello World'); +``` + +**Warning**: the SPI module is untested + +### new _constructor_(channel, speed) + +Instantiates a new SPI instance with the given channel, which must be 0 or 1, at the specified speed in bps, which must be +between 500000 and 32000000. + +## SPI Instances + +### data_out readWrite(data_in) + +Simultaneously reads and writes data to/from the SPI device. + +**Note:** If you encounter a "No such file or directory" error when trying to use SPI peripherals, you may need to load the SPI driver from the command line with: -```python -wiringpi.softToneCreate(PIN) -wiringpi.softToneWrite(PIN, FREQUENCY) ``` +gpio load spi +``` + +## UART + +Interfacing with a UART-compatible device (i.e. TTY devices) requires instantiating a UART instance for a device at a given BAUD rate. + +```javascript +var raspi = require('raspi-llio'); + +var uart = new raspi.UART('/dev/ttyAMA0', 115200); +setInterval(function() { + var data = ''; + while (uart.dataAvailable()) { + data += uart.getCharacter(); + }; + if (data) { + console.log(data); + } +}, 500); +``` + +**Warning**: the UART module is untested + +### new _constructor_(device, baud) + +Instantiates a UART instance for the given device (e.g. ```/dev/tty0```) at a given BAUD rate, which must be a positive integer. + +## UART Instances + +### write(data) + +Writes the given string to the UART device. + +### amount dataAvailable() + +Returns the number of characters available for reading. + +### char getCharacter() + +Gets a single character from the device. Blocks for up to 10 seconds before throwing an error if no data is available. + +### flush() + +Flushes the serial device. + +## Further Reading + +You may also be interested in the [Raspi IO](https://github.com/bryan-m-hughes/raspi-io) library, which provides a more abstract API that is compatible with [Johnny-Five](https://github.com/rwaldron/johnny-five). + +License +======= + +The MIT License (MIT) + +Copyright (c) 2014 Bryan Hughes + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the 'Software'), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. -**Bit shifting:** ```python wiringpi.shiftOut(1, 2, 0, 123) # Shift out 123 (b1110110, byte 0-255) to data pin 1, clock pin 2