From a1a494f7f02a25bad9ec7377152b8c7efd463422 Mon Sep 17 00:00:00 2001 From: Jason Kridner <jkridner@beagleboard.org> Date: Wed, 14 Sep 2022 12:47:02 -0400 Subject: [PATCH] books/beaglebone-cookbook: move code to git submodule repo --- .gitlab-ci.yml | 3 + .gitmodules | 3 + books/beaglebone-cookbook/01basics/basics.rst | 8 +- .../beaglebone-cookbook/02sensors/code/GPS.js | 29 --- .../02sensors/code/analogIn.js | 30 --- .../02sensors/code/analogIn.py | 31 --- .../02sensors/code/audio.asoundrc | 10 - .../02sensors/code/audio.js | 46 ---- .../02sensors/code/bone_eqep2b.dts | 61 ----- .../02sensors/code/encoder.js | 17 -- .../02sensors/code/gpiod/.gitignore | 6 - .../02sensors/code/gpiod/Makefile | 32 --- .../02sensors/code/gpiod/ReadMe.md | 23 -- .../02sensors/code/gpiod/aggregatorSetup.sh | 47 ---- .../02sensors/code/gpiod/bulk_blink.py | 46 ---- .../02sensors/code/gpiod/get.c | 52 ---- .../02sensors/code/gpiod/get.py | 34 --- .../02sensors/code/gpiod/get.sh | 8 - .../02sensors/code/gpiod/getset.c | 70 ------ .../02sensors/code/gpiod/getset.py | 37 --- .../02sensors/code/gpiod/getsetEvent.c | 85 ------- .../02sensors/code/gpiod/getsetEvent.py | 55 ----- .../02sensors/code/gpiod/toggle1.c | 61 ----- .../02sensors/code/gpiod/toggle1.py | 27 -- .../02sensors/code/gpiod/toggle1.sh | 7 - .../02sensors/code/gpiod/toggle2.c | 66 ----- .../02sensors/code/gpiod/toggle2.py | 28 --- .../02sensors/code/gpiod/toggleLED.c | 66 ----- .../02sensors/code/gpiod/toggleLED.py | 24 -- .../02sensors/code/hc-sr04-ultraSonic.js | 51 ---- .../02sensors/code/i2c-scan.js | 19 -- .../02sensors/code/i2c-test.js | 29 --- .../02sensors/code/i2cTemp.js | 22 -- .../02sensors/code/i2cTemp.py | 22 -- .../02sensors/code/i2ctmp101.py | 19 -- .../02sensors/code/pushbutton.js | 28 --- .../02sensors/code/pushbutton.py | 33 --- .../02sensors/code/pushbutton2.js | 10 - .../02sensors/code/pushbuttonPullup.js | 34 --- .../02sensors/code/pushbutton_digitalRead.js | 11 - .../02sensors/code/rotaryEncoder.js | 39 --- .../02sensors/code/rotaryEncoder.py | 43 ---- .../02sensors/code/sensorTag.js | 103 -------- .../02sensors/code/stop.js | 10 - .../02sensors/code/testHC-SR04.js | 37 --- .../02sensors/code/ultrasonicRange.js | 30 --- .../02sensors/code/ultrasonicRange.py | 30 --- .../beaglebone-cookbook/02sensors/code/w1.js | 23 -- .../beaglebone-cookbook/02sensors/code/w1.py | 23 -- .../beaglebone-cookbook/02sensors/sensors.rst | 64 ++--- .../03displays/code/externLED.js | 33 --- .../03displays/code/externLED.py | 40 --- .../03displays/code/fadeLED.js | 44 ---- .../03displays/code/fadeLED.py | 44 ---- .../03displays/code/internLED.js | 25 -- .../03displays/code/internLED.py | 26 -- .../03displays/code/matrixLEDi2c.js | 45 ---- .../03displays/code/matrixLEDi2c.py | 41 ---- .../03displays/code/neoPixel.sh | 19 -- .../03displays/code/nokia5110.js | 18 -- .../03displays/code/nokia5110Test.js | 231 ------------------ .../03displays/code/pwmTest.sh | 22 -- .../03displays/code/speak.js | 27 -- .../03displays/displays.rst | 34 +-- .../04motors/code/bipolarStepperMotor.py | 91 ------- .../04motors/code/dcMotor.js | 44 ---- .../04motors/code/dcMotor.py | 50 ---- .../04motors/code/h-bridgeMotor.js | 54 ---- .../beaglebone-cookbook/04motors/code/ring.js | 40 --- .../04motors/code/servoBird.js | 22 -- .../04motors/code/servoEncoder.py | 98 -------- .../04motors/code/servoMotor.js | 50 ---- .../04motors/code/servoMotor.py | 56 ----- .../04motors/code/servoSense.js | 46 ---- .../beaglebone-cookbook/04motors/code/stop.js | 10 - .../04motors/code/unipolarStepperMotor.js | 72 ------ .../code/unipolarStepperMotor.js.diff | 6 - .../04motors/code/unipolarStepperMotor.py | 91 ------- .../code/unipolarStepperMotor.py.diff | 6 - books/beaglebone-cookbook/04motors/motors.rst | 38 +-- .../05tips/code/blinkLED.c | 48 ---- .../05tips/code/blinkLED.py | 13 - .../05tips/code/ipMasquerade.sh | 31 --- .../beaglebone-cookbook/05tips/code/setDNS.sh | 40 --- books/beaglebone-cookbook/05tips/tips.rst | 12 +- .../06iot/code/GPIOserver.js | 59 ----- .../06iot/code/analogInContinuous.py | 91 ------- .../06iot/code/emailTest.py | 24 -- .../06iot/code/flask/app1.py | 22 -- .../06iot/code/flask/app2.py | 36 --- .../06iot/code/flask/app3.py | 60 ----- .../06iot/code/flask/app4.py | 79 ------ .../06iot/code/flask/app5.py | 87 ------- .../06iot/code/flask/flask.service | 10 - .../06iot/code/flask/helloWorld.py | 10 - .../06iot/code/flask/install.sh | 7 - .../06iot/code/flask/ngrok.yml | 4 - .../06iot/code/flask/setup.sh | 2 - .../06iot/code/flask/static/favicon.ico | Bin 562718 -> 0 bytes .../06iot/code/flask/static/style.css | 15 -- .../06iot/code/flask/templates/index1.html | 9 - .../06iot/code/flask/templates/index2.html | 10 - .../06iot/code/flask/templates/index3.html | 17 -- .../06iot/code/flask/templates/index4.html | 20 -- .../06iot/code/flask/templates/index5.html | 21 -- .../06iot/code/flotDemo.html | 15 -- .../06iot/code/flotDemo.js | 66 ----- .../06iot/code/jQueryDemo.js | 34 --- .../06iot/code/jQueryInstall.sh | 2 - .../06iot/code/launchPad.js | 37 --- .../06iot/code/launchPad/launchPad.ino | 44 ---- .../06iot/code/nodemailer-install.sh | 1 - .../06iot/code/nodemailer-test.js | 38 --- .../06iot/code/noderedExample.json | 164 ------------- .../06iot/code/processingDemo.js | 89 ------- .../beaglebone-cookbook/06iot/code/server.js | 37 --- .../beaglebone-cookbook/06iot/code/test.html | 10 - .../06iot/code/twilio-test.js | 39 --- .../06iot/code/twilioSetup.sh | 2 - .../06iot/code/twilioTest.py | 20 -- .../06iot/code/twitterInstall.sh | 4 - .../06iot/code/twitterKeys.sh | 10 - .../06iot/code/twitterPushbutton.js | 39 --- .../06iot/code/twitterSearch.js | 20 -- .../06iot/code/twitterStream.js | 44 ---- .../06iot/code/twitterTimeLine.js | 25 -- .../06iot/code/twitterUpload.js | 32 --- .../06iot/code/twitter_create_tweet.py | 75 ------ .../06iot/code/twitter_delete_tweet.py | 72 ------ .../06iot/code/twitter_recent_search.py | 42 ---- .../06iot/code/twitter_user_tweets.py | 60 ----- .../beaglebone-cookbook/06iot/code/weather.py | 46 ---- .../06iot/code/weatherSetup.sh | 2 - books/beaglebone-cookbook/06iot/code/xbee.js | 2 - books/beaglebone-cookbook/06iot/iot.rst | 76 +++--- .../07kernel/code/Makefile | 8 - .../07kernel/code/Makefile.display | 8 - .../beaglebone-cookbook/07kernel/code/hello.c | 22 -- .../07kernel/code/hello.patch | 53 ---- .../07kernel/code/helloWorld.c | 5 - books/beaglebone-cookbook/07kernel/kernel.rst | 26 +- .../08realtime/code/pushLED.c | 68 ------ .../08realtime/code/pushLED.js | 39 --- .../08realtime/code/pushLED.py | 49 ---- .../08realtime/code/pushLEDmmap.c | 68 ------ .../08realtime/code/pushLEDmmap.h | 35 --- .../08realtime/code/rt/cyclictest.png | Bin 6556 -> 0 bytes .../08realtime/code/rt/hist.gen | 4 - .../08realtime/code/rt/hist.plt | 17 -- .../08realtime/code/rt/install.sh | 3 - .../08realtime/code/rt/setup.sh | 3 - .../08realtime/realtime.rst | 30 +-- .../09capes/code/quickBot_motor_test.js | 116 --------- books/beaglebone-cookbook/code | 1 + 154 files changed, 150 insertions(+), 5394 deletions(-) create mode 100644 .gitmodules delete mode 100755 books/beaglebone-cookbook/02sensors/code/GPS.js delete mode 100755 books/beaglebone-cookbook/02sensors/code/analogIn.js delete mode 100644 books/beaglebone-cookbook/02sensors/code/analogIn.py delete mode 100644 books/beaglebone-cookbook/02sensors/code/audio.asoundrc delete mode 100755 books/beaglebone-cookbook/02sensors/code/audio.js delete mode 100644 books/beaglebone-cookbook/02sensors/code/bone_eqep2b.dts delete mode 100644 books/beaglebone-cookbook/02sensors/code/encoder.js delete mode 100644 books/beaglebone-cookbook/02sensors/code/gpiod/.gitignore delete mode 100644 books/beaglebone-cookbook/02sensors/code/gpiod/Makefile delete mode 100644 books/beaglebone-cookbook/02sensors/code/gpiod/ReadMe.md delete mode 100644 books/beaglebone-cookbook/02sensors/code/gpiod/aggregatorSetup.sh delete mode 100755 books/beaglebone-cookbook/02sensors/code/gpiod/bulk_blink.py delete mode 100644 books/beaglebone-cookbook/02sensors/code/gpiod/get.c delete mode 100755 books/beaglebone-cookbook/02sensors/code/gpiod/get.py delete mode 100755 books/beaglebone-cookbook/02sensors/code/gpiod/get.sh delete mode 100644 books/beaglebone-cookbook/02sensors/code/gpiod/getset.c delete mode 100755 books/beaglebone-cookbook/02sensors/code/gpiod/getset.py delete mode 100644 books/beaglebone-cookbook/02sensors/code/gpiod/getsetEvent.c delete mode 100755 books/beaglebone-cookbook/02sensors/code/gpiod/getsetEvent.py delete mode 100644 books/beaglebone-cookbook/02sensors/code/gpiod/toggle1.c delete mode 100755 books/beaglebone-cookbook/02sensors/code/gpiod/toggle1.py delete mode 100755 books/beaglebone-cookbook/02sensors/code/gpiod/toggle1.sh delete mode 100644 books/beaglebone-cookbook/02sensors/code/gpiod/toggle2.c delete mode 100755 books/beaglebone-cookbook/02sensors/code/gpiod/toggle2.py delete mode 100644 books/beaglebone-cookbook/02sensors/code/gpiod/toggleLED.c delete mode 100755 books/beaglebone-cookbook/02sensors/code/gpiod/toggleLED.py delete mode 100755 books/beaglebone-cookbook/02sensors/code/hc-sr04-ultraSonic.js delete mode 100755 books/beaglebone-cookbook/02sensors/code/i2c-scan.js delete mode 100755 books/beaglebone-cookbook/02sensors/code/i2c-test.js delete mode 100755 books/beaglebone-cookbook/02sensors/code/i2cTemp.js delete mode 100755 books/beaglebone-cookbook/02sensors/code/i2cTemp.py delete mode 100755 books/beaglebone-cookbook/02sensors/code/i2ctmp101.py delete mode 100755 books/beaglebone-cookbook/02sensors/code/pushbutton.js delete mode 100755 books/beaglebone-cookbook/02sensors/code/pushbutton.py delete mode 100755 books/beaglebone-cookbook/02sensors/code/pushbutton2.js delete mode 100755 books/beaglebone-cookbook/02sensors/code/pushbuttonPullup.js delete mode 100755 books/beaglebone-cookbook/02sensors/code/pushbutton_digitalRead.js delete mode 100755 books/beaglebone-cookbook/02sensors/code/rotaryEncoder.js delete mode 100755 books/beaglebone-cookbook/02sensors/code/rotaryEncoder.py delete mode 100755 books/beaglebone-cookbook/02sensors/code/sensorTag.js delete mode 100755 books/beaglebone-cookbook/02sensors/code/stop.js delete mode 100755 books/beaglebone-cookbook/02sensors/code/testHC-SR04.js delete mode 100755 books/beaglebone-cookbook/02sensors/code/ultrasonicRange.js delete mode 100755 books/beaglebone-cookbook/02sensors/code/ultrasonicRange.py delete mode 100755 books/beaglebone-cookbook/02sensors/code/w1.js delete mode 100755 books/beaglebone-cookbook/02sensors/code/w1.py delete mode 100755 books/beaglebone-cookbook/03displays/code/externLED.js delete mode 100755 books/beaglebone-cookbook/03displays/code/externLED.py delete mode 100755 books/beaglebone-cookbook/03displays/code/fadeLED.js delete mode 100755 books/beaglebone-cookbook/03displays/code/fadeLED.py delete mode 100755 books/beaglebone-cookbook/03displays/code/internLED.js delete mode 100755 books/beaglebone-cookbook/03displays/code/internLED.py delete mode 100755 books/beaglebone-cookbook/03displays/code/matrixLEDi2c.js delete mode 100755 books/beaglebone-cookbook/03displays/code/matrixLEDi2c.py delete mode 100755 books/beaglebone-cookbook/03displays/code/neoPixel.sh delete mode 100644 books/beaglebone-cookbook/03displays/code/nokia5110.js delete mode 100755 books/beaglebone-cookbook/03displays/code/nokia5110Test.js delete mode 100755 books/beaglebone-cookbook/03displays/code/pwmTest.sh delete mode 100755 books/beaglebone-cookbook/03displays/code/speak.js delete mode 100755 books/beaglebone-cookbook/04motors/code/bipolarStepperMotor.py delete mode 100755 books/beaglebone-cookbook/04motors/code/dcMotor.js delete mode 100755 books/beaglebone-cookbook/04motors/code/dcMotor.py delete mode 100755 books/beaglebone-cookbook/04motors/code/h-bridgeMotor.js delete mode 100755 books/beaglebone-cookbook/04motors/code/ring.js delete mode 100755 books/beaglebone-cookbook/04motors/code/servoBird.js delete mode 100755 books/beaglebone-cookbook/04motors/code/servoEncoder.py delete mode 100755 books/beaglebone-cookbook/04motors/code/servoMotor.js delete mode 100755 books/beaglebone-cookbook/04motors/code/servoMotor.py delete mode 100755 books/beaglebone-cookbook/04motors/code/servoSense.js delete mode 100755 books/beaglebone-cookbook/04motors/code/stop.js delete mode 100755 books/beaglebone-cookbook/04motors/code/unipolarStepperMotor.js delete mode 100644 books/beaglebone-cookbook/04motors/code/unipolarStepperMotor.js.diff delete mode 100755 books/beaglebone-cookbook/04motors/code/unipolarStepperMotor.py delete mode 100644 books/beaglebone-cookbook/04motors/code/unipolarStepperMotor.py.diff delete mode 100755 books/beaglebone-cookbook/05tips/code/blinkLED.c delete mode 100755 books/beaglebone-cookbook/05tips/code/blinkLED.py delete mode 100755 books/beaglebone-cookbook/05tips/code/ipMasquerade.sh delete mode 100755 books/beaglebone-cookbook/05tips/code/setDNS.sh delete mode 100755 books/beaglebone-cookbook/06iot/code/GPIOserver.js delete mode 100755 books/beaglebone-cookbook/06iot/code/analogInContinuous.py delete mode 100755 books/beaglebone-cookbook/06iot/code/emailTest.py delete mode 100755 books/beaglebone-cookbook/06iot/code/flask/app1.py delete mode 100755 books/beaglebone-cookbook/06iot/code/flask/app2.py delete mode 100755 books/beaglebone-cookbook/06iot/code/flask/app3.py delete mode 100755 books/beaglebone-cookbook/06iot/code/flask/app4.py delete mode 100755 books/beaglebone-cookbook/06iot/code/flask/app5.py delete mode 100644 books/beaglebone-cookbook/06iot/code/flask/flask.service delete mode 100755 books/beaglebone-cookbook/06iot/code/flask/helloWorld.py delete mode 100644 books/beaglebone-cookbook/06iot/code/flask/install.sh delete mode 100644 books/beaglebone-cookbook/06iot/code/flask/ngrok.yml delete mode 100644 books/beaglebone-cookbook/06iot/code/flask/setup.sh delete mode 100644 books/beaglebone-cookbook/06iot/code/flask/static/favicon.ico delete mode 100644 books/beaglebone-cookbook/06iot/code/flask/static/style.css delete mode 100644 books/beaglebone-cookbook/06iot/code/flask/templates/index1.html delete mode 100644 books/beaglebone-cookbook/06iot/code/flask/templates/index2.html delete mode 100644 books/beaglebone-cookbook/06iot/code/flask/templates/index3.html delete mode 100644 books/beaglebone-cookbook/06iot/code/flask/templates/index4.html delete mode 100644 books/beaglebone-cookbook/06iot/code/flask/templates/index5.html delete mode 100644 books/beaglebone-cookbook/06iot/code/flotDemo.html delete mode 100644 books/beaglebone-cookbook/06iot/code/flotDemo.js delete mode 100644 books/beaglebone-cookbook/06iot/code/jQueryDemo.js delete mode 100644 books/beaglebone-cookbook/06iot/code/jQueryInstall.sh delete mode 100755 books/beaglebone-cookbook/06iot/code/launchPad.js delete mode 100644 books/beaglebone-cookbook/06iot/code/launchPad/launchPad.ino delete mode 100755 books/beaglebone-cookbook/06iot/code/nodemailer-install.sh delete mode 100755 books/beaglebone-cookbook/06iot/code/nodemailer-test.js delete mode 100644 books/beaglebone-cookbook/06iot/code/noderedExample.json delete mode 100644 books/beaglebone-cookbook/06iot/code/processingDemo.js delete mode 100755 books/beaglebone-cookbook/06iot/code/server.js delete mode 100644 books/beaglebone-cookbook/06iot/code/test.html delete mode 100755 books/beaglebone-cookbook/06iot/code/twilio-test.js delete mode 100755 books/beaglebone-cookbook/06iot/code/twilioSetup.sh delete mode 100755 books/beaglebone-cookbook/06iot/code/twilioTest.py delete mode 100644 books/beaglebone-cookbook/06iot/code/twitterInstall.sh delete mode 100755 books/beaglebone-cookbook/06iot/code/twitterKeys.sh delete mode 100755 books/beaglebone-cookbook/06iot/code/twitterPushbutton.js delete mode 100755 books/beaglebone-cookbook/06iot/code/twitterSearch.js delete mode 100755 books/beaglebone-cookbook/06iot/code/twitterStream.js delete mode 100755 books/beaglebone-cookbook/06iot/code/twitterTimeLine.js delete mode 100755 books/beaglebone-cookbook/06iot/code/twitterUpload.js delete mode 100755 books/beaglebone-cookbook/06iot/code/twitter_create_tweet.py delete mode 100755 books/beaglebone-cookbook/06iot/code/twitter_delete_tweet.py delete mode 100755 books/beaglebone-cookbook/06iot/code/twitter_recent_search.py delete mode 100755 books/beaglebone-cookbook/06iot/code/twitter_user_tweets.py delete mode 100755 books/beaglebone-cookbook/06iot/code/weather.py delete mode 100755 books/beaglebone-cookbook/06iot/code/weatherSetup.sh delete mode 100644 books/beaglebone-cookbook/06iot/code/xbee.js delete mode 100644 books/beaglebone-cookbook/07kernel/code/Makefile delete mode 100644 books/beaglebone-cookbook/07kernel/code/Makefile.display delete mode 100644 books/beaglebone-cookbook/07kernel/code/hello.c delete mode 100644 books/beaglebone-cookbook/07kernel/code/hello.patch delete mode 100644 books/beaglebone-cookbook/07kernel/code/helloWorld.c delete mode 100755 books/beaglebone-cookbook/08realtime/code/pushLED.c delete mode 100755 books/beaglebone-cookbook/08realtime/code/pushLED.js delete mode 100755 books/beaglebone-cookbook/08realtime/code/pushLED.py delete mode 100644 books/beaglebone-cookbook/08realtime/code/pushLEDmmap.c delete mode 100644 books/beaglebone-cookbook/08realtime/code/pushLEDmmap.h delete mode 100644 books/beaglebone-cookbook/08realtime/code/rt/cyclictest.png delete mode 100755 books/beaglebone-cookbook/08realtime/code/rt/hist.gen delete mode 100755 books/beaglebone-cookbook/08realtime/code/rt/hist.plt delete mode 100755 books/beaglebone-cookbook/08realtime/code/rt/install.sh delete mode 100755 books/beaglebone-cookbook/08realtime/code/rt/setup.sh delete mode 100755 books/beaglebone-cookbook/09capes/code/quickBot_motor_test.js create mode 160000 books/beaglebone-cookbook/code diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 66142ecb..466b2731 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,5 +1,8 @@ image: beagle/sphinx-build-env:latest +variables: + GIT_SUBMODULE_STRATEGY: recursive + stages: - deploy diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 00000000..0c170ef1 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "books/beaglebone-cookbook/code"] + path = books/beaglebone-cookbook/code + url = https://git.beagleboard.org/beagleboard/beaglebone-cookbook-code.git diff --git a/books/beaglebone-cookbook/01basics/basics.rst b/books/beaglebone-cookbook/01basics/basics.rst index 8ff3dddc..89273383 100644 --- a/books/beaglebone-cookbook/01basics/basics.rst +++ b/books/beaglebone-cookbook/01basics/basics.rst @@ -170,15 +170,13 @@ Connect your Bone to the Internet and log into it. From the command line run: .. code-block:: - bone$ git clone git@github.com:MarkAYoder/BoneCookbook.git - bone$ cd BoneCookbook/docs + bone$ git clone https://git.beagleboard.org/beagleboard/beaglebone-cookbook-code + bone$ cd beaglebone-cookbook-code bone$ ls You can look around from the command line, or explore from Visual Sudio Code. If you ar using VSC, go to the *File* menu and select *Open Folder ...* and -select BoneCookbook/docs. Then explore. You'll find there is a directory -for each chapter and most chapters have a *code* directory for the sample -scripts and a *figures* directory for the figures. +select beaglebone-cookbook-code. Then explore. .. _basics_wire_breadboard: diff --git a/books/beaglebone-cookbook/02sensors/code/GPS.js b/books/beaglebone-cookbook/02sensors/code/GPS.js deleted file mode 100755 index fd81970d..00000000 --- a/books/beaglebone-cookbook/02sensors/code/GPS.js +++ /dev/null @@ -1,29 +0,0 @@ -#!/usr/bin/env node -// Install with: npm install nmea - -// Need to add exports.serialParsers = m.module.parsers; -// to the end of /usr/local/lib/node_modules/bonescript/serial.js - -var b = require('bonescript'); -var nmea = require('nmea'); - -var port = '/dev/ttyO4'; -var options = { - baudrate: 9600, - parser: b.serialParsers.readline("\n") -}; - -b.serialOpen(port, options, onSerial); - -function onSerial(x) { - if (x.err) { - console.log('***ERROR*** ' + JSON.stringify(x)); - } - if (x.event == 'open') { - console.log('***OPENED***'); - } - if (x.event == 'data') { - console.log(String(x.data)); - console.log(nmea.parse(x.data)); - } -} diff --git a/books/beaglebone-cookbook/02sensors/code/analogIn.js b/books/beaglebone-cookbook/02sensors/code/analogIn.js deleted file mode 100755 index 62136407..00000000 --- a/books/beaglebone-cookbook/02sensors/code/analogIn.js +++ /dev/null @@ -1,30 +0,0 @@ -#!/usr/bin/env node -////////////////////////////////////// -// analogin.js -// Reads the analog value of the light sensor. -////////////////////////////////////// -const fs = require("fs"); -const ms = 500; // Time in milliseconds - -const pin = "2"; // light sensor, A2, P9_37 - -const IIOPATH='/sys/bus/iio/devices/iio:device0/in_voltage'+pin+'_raw'; - -console.log('Hit ^C to stop'); - -// Read every 500ms -setInterval(readPin, ms); - -function readPin() { - var data = fs.readFileSync(IIOPATH).slice(0, -1); - console.log('data = ' + data); - } -// Bone | Pocket | AIN -// ----- | ------ | --- -// P9_39 | P1_19 | 0 -// P9_40 | P1_21 | 1 -// P9_37 | P1_23 | 2 -// P9_38 | P1_25 | 3 -// P9_33 | P1_27 | 4 -// P9_36 | P2_35 | 5 -// P9_35 | P1_02 | 6 diff --git a/books/beaglebone-cookbook/02sensors/code/analogIn.py b/books/beaglebone-cookbook/02sensors/code/analogIn.py deleted file mode 100644 index c62abd1b..00000000 --- a/books/beaglebone-cookbook/02sensors/code/analogIn.py +++ /dev/null @@ -1,31 +0,0 @@ -#!/usr/bin/env python3 -#////////////////////////////////////// -# analogin.py -# Reads the analog value of the light sensor. -#////////////////////////////////////// -import time -import os - -pin = "2" # light sensor, A2, P9_37 - -IIOPATH='/sys/bus/iio/devices/iio:device0/in_voltage'+pin+'_raw' - -print('Hit ^C to stop') - -f = open(IIOPATH, "r") - -while True: - f.seek(0) - x = float(f.read())/4096 - print('{}: {:.1f}%, {:.3f} V'.format(pin, 100*x, 1.8*x), end = '\r') - time.sleep(0.1) - -# // Bone | Pocket | AIN -# // ----- | ------ | --- -# // P9_39 | P1_19 | 0 -# // P9_40 | P1_21 | 1 -# // P9_37 | P1_23 | 2 -# // P9_38 | P1_25 | 3 -# // P9_33 | P1_27 | 4 -# // P9_36 | P2_35 | 5 -# // P9_35 | P1_02 | 6 diff --git a/books/beaglebone-cookbook/02sensors/code/audio.asoundrc b/books/beaglebone-cookbook/02sensors/code/audio.asoundrc deleted file mode 100644 index 8fcc9b97..00000000 --- a/books/beaglebone-cookbook/02sensors/code/audio.asoundrc +++ /dev/null @@ -1,10 +0,0 @@ -pcm.!default { - type plug - slave { - pcm "hw:1,0" - } -} -ctl.!default { - type hw - card 1 -} diff --git a/books/beaglebone-cookbook/02sensors/code/audio.js b/books/beaglebone-cookbook/02sensors/code/audio.js deleted file mode 100755 index eeca6ca3..00000000 --- a/books/beaglebone-cookbook/02sensors/code/audio.js +++ /dev/null @@ -1,46 +0,0 @@ -#!/usr/bin/node -// 'childprocess' help at: -// http://nodejs.org/api/child_process.html\ -// #child_process_child_process_spawn_command_args_options -"use strict"; - -var b = require('bonescript'), - spawn = require('child_process').spawn; - -var audioRate = 48000, - bufferSize = 4800, - format = "S16_LE"; // 16-bit signed, little endian - -var audioIn = spawn( - "/usr/bin/arecord", - [ - "-c2", "-r"+audioRate, "-f"+format, "-traw", - "--buffer-size="+bufferSize, "--period-size="+bufferSize, "-N" - ] - ); - - var audioOut = spawn( - "/usr/bin/aplay", - [ - "-c2", "-r"+audioRate, "-f"+format, "-traw", - "--buffer-size="+bufferSize, "--period-size="+bufferSize, "-N" - ] - ); - - audioIn.stdout.on('data', function(data) { - audioOut.stdin.write(data); - }); - - audioIn.on('close', function(code) { - if(code !== 0) { - console.log('arecord process exited with code: ' + code); - audioOut.stdin.end(); - } - }) - - audioOut.on('close', function(code) { - if(code !== 0) { - console.log('aplay process exited with code: ' + code); - } - }) - \ No newline at end of file diff --git a/books/beaglebone-cookbook/02sensors/code/bone_eqep2b.dts b/books/beaglebone-cookbook/02sensors/code/bone_eqep2b.dts deleted file mode 100644 index 036cdcd3..00000000 --- a/books/beaglebone-cookbook/02sensors/code/bone_eqep2b.dts +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (C) 2013 Nathaniel R. Lewis - http://nathanielrlewis.com/ - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Enable eQEP2 on the Beaglebone White and Black - * These pins don't conflict with the HDMI - */ -/dts-v1/; -/plugin/; - -/ { - compatible = "ti,beaglebone", "ti,beaglebone-black"; - - /* identification */ - part-number = "bone_eqep2"; - version = "00A0"; - - fragment@0 { - target = <&am33xx_pinmux>; - __overlay__ { - pinctrl_eqep2: pinctrl_eqep2_pins { - pinctrl-single,pins = < - 0x038 0x24 /* P8_16 = GPIO2_12 = EQEP2_index, MODE4 */ - 0x03C 0x24 /* P8_15 = GPIO2_13 = EQEP2_strobe, MODE4 */ - 0x030 0x34 /* P8_12 = GPIO2_10 = EQEP2A_in, MODE4 */ - 0x034 0x34 /* P8_11 = GPIO2_11 = EQEP2B_in, MODE4 */ - >; - }; - }; - }; - - fragment@1 { - target = <&epwmss2>; - __overlay__ { - status = "okay"; - }; - }; - - fragment@2 { - target = <&eqep2>; - __overlay__ { - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_eqep2>; - count_mode = < 0 >; - /* 0 - Quadrature mode, normal 90 phase offset cha & chb. - 1 - Direction mode. cha input = clock, chb input = direction */ - swap_inputs = < 0 >; /* Are chan A & chan B swapped? (0-no,1-yes) */ - invert_qa = < 1 >; /* Should we invert the channel A input? */ - invert_qb = < 1 >; /* Should we invert the channel B input? - These are inverted because my encoder outputs drive transistors - that pull down the pins */ - invert_qi = < 0 >; /* Should we invert the index input? */ - invert_qs = < 0 >; /* Should we invert the strobe input? */ - - status = "okay"; - }; - }; -}; diff --git a/books/beaglebone-cookbook/02sensors/code/encoder.js b/books/beaglebone-cookbook/02sensors/code/encoder.js deleted file mode 100644 index 7ad2f4d4..00000000 --- a/books/beaglebone-cookbook/02sensors/code/encoder.js +++ /dev/null @@ -1,17 +0,0 @@ -#!/usr/bin/env node -// Test this -var b = require('bonescript'); -var encoder = ''; - -function printStatus(x) { - console.log('x.value = ' + x.value); - console.log('x.err = ' + x.err); -} - -function onEncoderReady(e) { - if(e.event == 'return') { - b.encoderRead(encoder, printStatus); - } -} - -b.encoderOpen(encoder, {}, onEncoderReady); diff --git a/books/beaglebone-cookbook/02sensors/code/gpiod/.gitignore b/books/beaglebone-cookbook/02sensors/code/gpiod/.gitignore deleted file mode 100644 index fecb0575..00000000 --- a/books/beaglebone-cookbook/02sensors/code/gpiod/.gitignore +++ /dev/null @@ -1,6 +0,0 @@ -toggle1 -toggle2 -get -getset -getsetEvent -toggleLED diff --git a/books/beaglebone-cookbook/02sensors/code/gpiod/Makefile b/books/beaglebone-cookbook/02sensors/code/gpiod/Makefile deleted file mode 100644 index b5267491..00000000 --- a/books/beaglebone-cookbook/02sensors/code/gpiod/Makefile +++ /dev/null @@ -1,32 +0,0 @@ -# -# Programs -# -all: toggle1 toggle2 get getset getsetEvent toggleLED - -toggle1: toggle1.c - $(CC) $(LDFLAGS) -o $@ $^ -lgpiod - -toggle2: toggle2.c - $(CC) $(LDFLAGS) -o $@ $^ -lgpiod - -get: get.c - $(CC) $(LDFLAGS) -o $@ $^ -lgpiod - -getset: getset.c - $(CC) $(LDFLAGS) -o $@ $^ -lgpiod - -getsetEvent: getsetEvent.c - $(CC) $(LDFLAGS) -o $@ $^ -lgpiod - -toggleLED: toggleLED.c - $(CC) $(LDFLAGS) -o $@ $^ -lgpiod - -# -# Objects -# - -%.o: %.c - $(CC) $(CFLAGS) -c $< -o $@ - -clean: - rm toggle1 toggle2 get getset getsetEvent toggleLED diff --git a/books/beaglebone-cookbook/02sensors/code/gpiod/ReadMe.md b/books/beaglebone-cookbook/02sensors/code/gpiod/ReadMe.md deleted file mode 100644 index 4a8d2212..00000000 --- a/books/beaglebone-cookbook/02sensors/code/gpiod/ReadMe.md +++ /dev/null @@ -1,23 +0,0 @@ -libgpiod is a new C library and tools for interacting with the linux GPIO -character device. -Detailed information is -[here](https://git.kernel.org/pub/scm/libs/libgpiod/libgpiod.git/tree/README) -and [Adafruit](https://blog.adafruit.com/2018/11/26/sysfs-is-dead-long-live-libgpiod-libgpiod-for-linux-circuitpython/) -also has information. - -One of the advantages of gpiod is that it can toggle multiple bits on the same -gpio chip at the same time. The toggle2 examples show how it's done. - -The directory contains examples of using gpiod with **C** and **python** to read/write -a gpio pin. - -File | Description ----- | ----------- -[toggle1](toggle1.c) | Toggles one pin as fast as possible. (300KHz in C, 57KHz in python) -[toggle2](toggle2.c) | Toggles two pins as fast as possible. (280KHz in C, 55KHz in python) -[get](get.c) | Reads an input pin and prints its value. -[getset](getset.c) | Reads an input pin and writes its value to an output pin. (5us delay in C, 20 us Delay in python) -[getsetEvent](getset.c) | Like **getset**, but uses events. (40 us delay in C, 75 us delay in python) -[toggleLED](toggleLED.c) | Toggles the four built in USR LEDs. - -> Tip: Use **gpioinfo** to lookup chip and line numbers for various pins. diff --git a/books/beaglebone-cookbook/02sensors/code/gpiod/aggregatorSetup.sh b/books/beaglebone-cookbook/02sensors/code/gpiod/aggregatorSetup.sh deleted file mode 100644 index edc4d387..00000000 --- a/books/beaglebone-cookbook/02sensors/code/gpiod/aggregatorSetup.sh +++ /dev/null @@ -1,47 +0,0 @@ -# See: https://elinux.org/EBC_Exercise_51_GPIO_aggregator - -# Insert the module -sudo modprobe gpio-aggregator -# Go to the aggregator -cd /sys/bus/platform/drivers/gpio-aggregator -# Fix the modes -sudo chgrp gpio * -sudo chmod g+w * -# See what's there before adding a new chip -gpiodetect -# gpiochip0 [gpio-0-31] (32 lines) -# gpiochip1 [gpio-32-63] (32 lines) -# gpiochip2 [gpio-64-95] (32 lines) -# gpiochip3 [gpio-96-127] (32 lines) - -# Add a new chip mapping P9_14, P9_16, P9_18 and P9_22 -gpioinfo | grep -e chip -e P9_1[468] -e P9_22 -# gpiochip0 - 32 lines: -# line 2: "P9_22 [spi0_sclk]" "gpio-aggregator.0" input active-high [used] -# line 4: "P9_18 [spi0_d1]" "gpio-aggregator.0" output active-high [used] -# gpiochip1 - 32 lines: -# line 18: "P9_14 [ehrpwm1a]" "gpio-aggregator.0" output active-high [used] -# line 19: "P9_16 [ehrpwm1b]" "gpio-aggregator.0" input active-high [used] -# gpiochip2 - 32 lines: -# gpiochip3 - 32 lines: - -echo "gpio-32-63 18,19 gpio-0-31 4,2" > new_device -# Check to see if they are there -gpiodetect -# gpiochip0 [gpio-0-31] (32 lines) -# gpiochip1 [gpio-32-63] (32 lines) -# gpiochip2 [gpio-64-95] (32 lines) -# gpiochip3 [gpio-96-127] (32 lines) -# gpiochip4 [gpio-aggregator.0] (4 lines) - -gpioinfo | tail -6 -# line 31: "NC" unused input active-high -# gpiochip4 - 4 lines: -# line 0: unnamed unused output active-high -# line 1: unnamed unused input active-high -# line 2: unnamed unused input active-high -# line 3: unnamed unused output active-high - -# Turn them all on, then off -gpioset gpiochip4 0=1 1=1 2=1 3=1 -gpioset gpiochip4 0=0 1=0 2=0 3=0 diff --git a/books/beaglebone-cookbook/02sensors/code/gpiod/bulk_blink.py b/books/beaglebone-cookbook/02sensors/code/gpiod/bulk_blink.py deleted file mode 100755 index 7599325c..00000000 --- a/books/beaglebone-cookbook/02sensors/code/gpiod/bulk_blink.py +++ /dev/null @@ -1,46 +0,0 @@ -#!/usr/bin/env python3 -# ////////////////////////////////////// -# bulk_blink.py -# Toggles given pins as fast as it can. -# Given pins must be on the same gpiochip -# P9_14 is line 18 P9_16 is line 19. -# Run gpioinfo to see which pins are where. -# Wiring: Attach an oscilloscope to P9_14 and P9_16 to see the squarewave or -# uncomment the sleep and attach an LED. -# Setup: sudo apt update; pip install gpiod -# See: https://git.kernel.org/pub/scm/libs/libgpiod/libgpiod.git/tree/bindings/python/examples -# ////////////////////////////////////// -import sys -import time -import gpiod - -try: - if len(sys.argv) > 2: - LED_CHIP = sys.argv[1] - LED_LINE_OFFSETS = [] - for i in range(len(sys.argv) - 2): - LED_LINE_OFFSETS.append(int(sys.argv[i + 2])) - else: - raise Exception() -# pylint: disable=broad-except -except Exception: - print( - "Usage:" - + " python3 -m gpiod.test.bulk_blink <chip> <line offset1>" - + " [<line offset2> ...]" - ) - sys.exit() - -chip = gpiod.Chip(LED_CHIP) -lines = chip.get_lines(LED_LINE_OFFSETS) - -lines.request(consumer='Bulk Blink', type=gpiod.LINE_REQ_DIR_OUT) - -off = [0] * len(LED_LINE_OFFSETS) -on = [1] * len(LED_LINE_OFFSETS) - -while True: - lines.set_values(off) - time.sleep(0.25) - lines.set_values(on) - time.sleep(0.25) diff --git a/books/beaglebone-cookbook/02sensors/code/gpiod/get.c b/books/beaglebone-cookbook/02sensors/code/gpiod/get.c deleted file mode 100644 index 4aeefe04..00000000 --- a/books/beaglebone-cookbook/02sensors/code/gpiod/get.c +++ /dev/null @@ -1,52 +0,0 @@ -// ////////////////////////////////////// -// get.c -// Get the value of P8_13. P8_13 is line 23 on chip 0. -// Wiring: Attach a switch to P8_13 and 3.3V -// Setup: sudo apt update; sudo apt install libgpiod-dev -// See: https://github.com/starnight/libgpiod-example/blob/master/libgpiod-led/main.c -// ////////////////////////////////////// -#include <gpiod.h> -#include <stdio.h> -#include <unistd.h> - -#define CONSUMER "Consumer" - -int main(int argc, char **argv) -{ - int chipnumber = 0; - unsigned int line_num = 23; // GPIO Pin P8_13 - struct gpiod_chip *chip; - struct gpiod_line *line; - int i, ret; - - chip = gpiod_chip_open_by_number(chipnumber); - if (!chip) { - perror("Open chip failed\n"); - goto end; - } - - line = gpiod_chip_get_line(chip, line_num); - if (!line) { - perror("Get line failed\n"); - goto close_chip; - } - - ret = gpiod_line_request_input(line, CONSUMER); - if (ret < 0) { - perror("Request line as intput failed\n"); - goto release_line; - } - - /* Get */ - while(1) { - printf("%d\r", gpiod_line_get_value(line)); - usleep(1000); - } - -release_line: - gpiod_line_release(line); -close_chip: - gpiod_chip_close(chip); -end: - return 0; -} diff --git a/books/beaglebone-cookbook/02sensors/code/gpiod/get.py b/books/beaglebone-cookbook/02sensors/code/gpiod/get.py deleted file mode 100755 index 05820068..00000000 --- a/books/beaglebone-cookbook/02sensors/code/gpiod/get.py +++ /dev/null @@ -1,34 +0,0 @@ -#!/usr/bin/env python3 -# ////////////////////////////////////// -# get.py -# Get the value of P8_13. P8_13 is line 23 on chip 0. -# Wiring: Attach a switch to P8_13 and 3.3V -# Setup: sudo apt uupdate; sudo apt install libgpiod-dev -# See: https://github.com/starnight/libgpiod-example/blob/master/libgpiod-led/main.c -# ////////////////////////////////////// - -import gpiod -import sys - -if len(sys.argv) < 3: # Use P8_13 if not given - CHIP='0' - offsets=[13] -else: - CHIP=sys.argv[1] - offsets = [] - for off in sys.argv[2:]: - offsets.append(int(off)) - -chip = gpiod.Chip(CHIP) - -lines = chip.get_lines(offsets) -lines.request(consumer=sys.argv[0], type=gpiod.LINE_REQ_DIR_IN) - -print("Hit ^C to stop") - -while True: - vals = lines.get_values() - - for val in vals: - print(val, end=' ') - print('\r', end='') diff --git a/books/beaglebone-cookbook/02sensors/code/gpiod/get.sh b/books/beaglebone-cookbook/02sensors/code/gpiod/get.sh deleted file mode 100755 index 54cc18ba..00000000 --- a/books/beaglebone-cookbook/02sensors/code/gpiod/get.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/bash -# Reads P8_13 via gpiod. P8_13 is chip 0 line 23 - -echo Hit ^c to stop - -while true; do - gpioget 0 23 | tr \\n \\r -done \ No newline at end of file diff --git a/books/beaglebone-cookbook/02sensors/code/gpiod/getset.c b/books/beaglebone-cookbook/02sensors/code/gpiod/getset.c deleted file mode 100644 index 207c7689..00000000 --- a/books/beaglebone-cookbook/02sensors/code/gpiod/getset.c +++ /dev/null @@ -1,70 +0,0 @@ -// ////////////////////////////////////// -// getset.c -// Get the value of P8_16 and write it to P9_14. -// P8_16 is line 14 on chip 1. P9_14 is line 18 of chip 1. -// Wiring: Attach a switch to P8_16 and 3.3V and an LED to P9_14. -// Setup: sudo apt uupdate; sudo apt install libgpiod-dev -// See: https://github.com/starnight/libgpiod-example/blob/master/libgpiod-led/main.c -// ////////////////////////////////////// -#include <gpiod.h> -#include <stdio.h> -#include <unistd.h> - -#define CONSUMER "Consumer" - -int main(int argc, char **argv) -{ - int chipnumber = 1; - unsigned int getline_num = 14; // GPIO Pin P8_16 - unsigned int setline_num = 18; // GPIO Pin P9_14 - unsigned int val; - struct gpiod_chip *chip; - struct gpiod_line *getline, *setline; - int i, ret; - - chip = gpiod_chip_open_by_number(chipnumber); - if (!chip) { - perror("Open chip failed\n"); - goto end; - } - - getline = gpiod_chip_get_line(chip, getline_num); - if (!getline) { - perror("Get line failed\n"); - goto close_chip; - } - - setline = gpiod_chip_get_line(chip, setline_num); - if (!setline) { - perror("Set line failed\n"); - goto close_chip; - } - - ret = gpiod_line_request_input(getline, CONSUMER); - if (ret < 0) { - perror("Request line as input failed\n"); - goto release_line; - } - - ret = gpiod_line_request_output(setline, CONSUMER, 0); - if (ret < 0) { - perror("Request line as output failed\n"); - goto release_line; - } - - /* Get */ - while(1) { - val = gpiod_line_get_value(getline); - gpiod_line_set_value(setline, val); - // printf("%d\r", val); - // usleep(1000); - } - -release_line: - gpiod_line_release(getline); - gpiod_line_release(setline); -close_chip: - gpiod_chip_close(chip); -end: - return 0; -} diff --git a/books/beaglebone-cookbook/02sensors/code/gpiod/getset.py b/books/beaglebone-cookbook/02sensors/code/gpiod/getset.py deleted file mode 100755 index 335807a9..00000000 --- a/books/beaglebone-cookbook/02sensors/code/gpiod/getset.py +++ /dev/null @@ -1,37 +0,0 @@ -#!/usr/bin/env python3 -# ////////////////////////////////////// -# getset.py -# Get the value of P8_16 and write it to P9_14. -# P8_16 is line 14 on chip 1. P9_14 is line 18 of chip 1. -# Wiring: Attach a switch to P8_16 and 3.3V and an LED to P9_14. -# Setup: sudo apt uupdate; sudo apt install libgpiod-dev -# See: https://github.com/starnight/libgpiod-example/blob/master/libgpiod-led/main.c -# ////////////////////////////////////// -# Based on https://git.kernel.org/pub/scm/libs/libgpiod/libgpiod.git/tree/bindings/python/examples - -import gpiod -import sys - -CONSUMER='getset' -CHIP='1' -getoffsets=[14] # P8_16 -setoffests=[18] # P9_14 - -chip = gpiod.Chip(CHIP) - -getlines = chip.get_lines(getoffsets) -getlines.request(consumer=CONSUMER, type=gpiod.LINE_REQ_DIR_IN) - -setlines = chip.get_lines(setoffests) -setlines.request(consumer=CONSUMER, type=gpiod.LINE_REQ_DIR_OUT) - -print("Hit ^C to stop") - -while True: - vals = getlines.get_values() - - # for val in vals: - # print(val, end=' ') - # print('\r', end='') - - setlines.set_values(vals) diff --git a/books/beaglebone-cookbook/02sensors/code/gpiod/getsetEvent.c b/books/beaglebone-cookbook/02sensors/code/gpiod/getsetEvent.c deleted file mode 100644 index b49ab2df..00000000 --- a/books/beaglebone-cookbook/02sensors/code/gpiod/getsetEvent.c +++ /dev/null @@ -1,85 +0,0 @@ -// ////////////////////////////////////// -// getsetEvent.c -// Like setset.c, but uses events -// Get the value of P8_16 and write it to P9_14. -// P8_16 is line 14 on chip 1. P9_14 is line 18 of chip 1. -// Wiring: Attach a switch to P8_16 and 3.3V and an LED to P9_14. -// Setup: sudo apt uupdate; sudo apt install libgpiod-dev -// See: https://github.com/starnight/libgpiod-example/blob/master/libgpiod-led/main.c -// ////////////////////////////////////// -#include <gpiod.h> -#include <stdio.h> -#include <unistd.h> - -#define CONSUMER "Consumer" - -int main(int argc, char **argv) -{ - int chipnumber = 1; - struct timespec ts = { 0, 1000000 }; // 1s Timeout for event - struct gpiod_line_event event; - unsigned int getline_num = 14; // GPIO Pin P8_16 - unsigned int setline_num = 18; // GPIO Pin P9_14 - unsigned int val; - struct gpiod_chip *chip; - struct gpiod_line *getline, *setline; - int i, ret; - - chip = gpiod_chip_open_by_number(chipnumber); - if (!chip) { - perror("Open chip failed\n"); - goto end; - } - - getline = gpiod_chip_get_line(chip, getline_num); - if (!getline) { - perror("Get line failed\n"); - goto close_chip; - } - - setline = gpiod_chip_get_line(chip, setline_num); - if (!setline) { - perror("Set line failed\n"); - goto close_chip; - } - - ret = gpiod_line_request_both_edges_events(getline, CONSUMER); - if (ret < 0) { - perror("Request line as input failed\n"); - goto release_line; - } - - ret = gpiod_line_request_output(setline, CONSUMER, 0); - if (ret < 0) { - perror("Request line as output failed\n"); - goto release_line; - } - - /* Get */ - while(1) { - do { - // printf("waiting...\n"); - ret = gpiod_line_event_wait(getline, &ts); - } while (ret <= 0); - - // I'm getting a Segment failt. event isn't correct. - // ret = gpiod_line_event_read(getline, &event); - // printf("ret: %d, event: %d\n", ret, event); - // if (!ret) - // printf("event: %s timestamp: [%8ld.%09ld]\n", - // event.event_type, event.ts.tv_sec, event.ts.tv_nsec); - - val = gpiod_line_get_value(getline); - gpiod_line_set_value(setline, val); - // printf("%d\n", val); - // usleep(1000); - } - -release_line: - gpiod_line_release(getline); - gpiod_line_release(setline); -close_chip: - gpiod_chip_close(chip); -end: - return 0; -} diff --git a/books/beaglebone-cookbook/02sensors/code/gpiod/getsetEvent.py b/books/beaglebone-cookbook/02sensors/code/gpiod/getsetEvent.py deleted file mode 100755 index 9240220f..00000000 --- a/books/beaglebone-cookbook/02sensors/code/gpiod/getsetEvent.py +++ /dev/null @@ -1,55 +0,0 @@ -#!/usr/bin/env python3 -# ////////////////////////////////////// -# getsetEvent.py -# Like getset.py but uses events. -# Get the value of P8_16 and write it to P9_14. -# P8_16 is line 14 on chip 1. P9_14 is line 18 of chip 1. -# Wiring: Attach a switch to P8_16 and 3.3V and an LED to P9_14. -# Setup: sudo apt uupdate; sudo apt install libgpiod-dev -# See: https://github.com/starnight/libgpiod-example/blob/master/libgpiod-led/main.c -# ////////////////////////////////////// -# Based on https://git.kernel.org/pub/scm/libs/libgpiod/libgpiod.git/tree/bindings/python/examples - -import gpiod -import sys - -CONSUMER='getset' -CHIP='1' -getoffsets=[14] # P8_16 -setoffests=[18] # P9_14 - -def print_event(event): - if event.type == gpiod.LineEvent.RISING_EDGE: - evstr = ' RISING EDGE' - elif event.type == gpiod.LineEvent.FALLING_EDGE: - evstr = 'FALLING EDGE' - else: - raise TypeError('Invalid event type') - - print('event: {} offset: {} timestamp: [{}.{}]'.format(evstr, - event.source.offset(), - event.sec, event.nsec)) - -chip = gpiod.Chip(CHIP) - -getlines = chip.get_lines(getoffsets) -getlines.request(consumer=CONSUMER, type=gpiod.LINE_REQ_EV_BOTH_EDGES) - -setlines = chip.get_lines(setoffests) -setlines.request(consumer=CONSUMER, type=gpiod.LINE_REQ_DIR_OUT) - -print("Hit ^C to stop") - -while True: - ev_lines = getlines.event_wait(sec=1) - if ev_lines: - for line in ev_lines: - event = line.event_read() - print_event(event) - vals = getlines.get_values() - - # for val in vals: - # print(val, end=' ') - # print('\r', end='') - - setlines.set_values(vals) diff --git a/books/beaglebone-cookbook/02sensors/code/gpiod/toggle1.c b/books/beaglebone-cookbook/02sensors/code/gpiod/toggle1.c deleted file mode 100644 index 1ff8c1cb..00000000 --- a/books/beaglebone-cookbook/02sensors/code/gpiod/toggle1.c +++ /dev/null @@ -1,61 +0,0 @@ -// ////////////////////////////////////// -// toggle1.c -// Toggles the P9_14 pin as fast as it can. P9_14 is line 18 on chip 1. -// Wiring: Attach an oscilloscope to P9_14 to see the squarewave or -// uncomment the usleep and attach an LED. -// Setup: sudo apt update; sudo apt install libgpiod-dev -// See: https://github.com/starnight/libgpiod-example/blob/master/libgpiod-led/main.c -// ////////////////////////////////////// -#include <gpiod.h> -#include <stdio.h> -#include <unistd.h> - -#define CONSUMER "Consumer" - -int main(int argc, char **argv) -{ - int chipnumber = 1; - unsigned int line_num = 18; // GPIO Pin P9_14 - unsigned int val; - struct gpiod_chip *chip; - struct gpiod_line *line; - int i, ret; - - chip = gpiod_chip_open_by_number(chipnumber); - if (!chip) { - perror("Open chip failed\n"); - goto end; - } - - line = gpiod_chip_get_line(chip, line_num); - if (!line) { - perror("Get line failed\n"); - goto close_chip; - } - - ret = gpiod_line_request_output(line, CONSUMER, 0); - if (ret < 0) { - perror("Request line as output failed\n"); - goto release_line; - } - - /* Blink */ - val = 0; - while(1) { - ret = gpiod_line_set_value(line, val); - if (ret < 0) { - perror("Set line output failed\n"); - goto release_line; - } - // printf("Output %u on line #%u\n", val, line_num); - usleep(100000); // Number of microseconds to sleep - val = !val; - } - -release_line: - gpiod_line_release(line); -close_chip: - gpiod_chip_close(chip); -end: - return 0; -} diff --git a/books/beaglebone-cookbook/02sensors/code/gpiod/toggle1.py b/books/beaglebone-cookbook/02sensors/code/gpiod/toggle1.py deleted file mode 100755 index d8b6d5d4..00000000 --- a/books/beaglebone-cookbook/02sensors/code/gpiod/toggle1.py +++ /dev/null @@ -1,27 +0,0 @@ -#!/usr/bin/env python3 -# ////////////////////////////////////// -# toggle1.py -# Toggles the P9_14 pin as fast as it can. P9_14 is line 18 on chip 1. -# Wiring: Attach an oscilloscope to P9_14 to see the squarewave or -# uncomment the sleep and attach an LED. -# Setup: sudo apt update; pip install gpiod -# See: https://git.kernel.org/pub/scm/libs/libgpiod/libgpiod.git/tree/bindings/python/examples -# ////////////////////////////////////// - -import gpiod -import time - -LED_CHIP = 'gpiochip1' -LED_LINE_OFFSET = [18] # P9_14 - -chip = gpiod.Chip(LED_CHIP) - -lines = chip.get_lines(LED_LINE_OFFSET) -lines.request(consumer='blink', type=gpiod.LINE_REQ_DIR_OUT) - -while True: - lines.set_values([0]) - time.sleep(0.1) - lines.set_values([1]) - time.sleep(0.1) - \ No newline at end of file diff --git a/books/beaglebone-cookbook/02sensors/code/gpiod/toggle1.sh b/books/beaglebone-cookbook/02sensors/code/gpiod/toggle1.sh deleted file mode 100755 index b27f9824..00000000 --- a/books/beaglebone-cookbook/02sensors/code/gpiod/toggle1.sh +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/bash -# gpio chip=1 line 18=P9_14 line19=P9_16 - -while true; do - gpioset 1 18=0 19=0 - gpioset 1 18=1 19=1 -done \ No newline at end of file diff --git a/books/beaglebone-cookbook/02sensors/code/gpiod/toggle2.c b/books/beaglebone-cookbook/02sensors/code/gpiod/toggle2.c deleted file mode 100644 index ad6b77f0..00000000 --- a/books/beaglebone-cookbook/02sensors/code/gpiod/toggle2.c +++ /dev/null @@ -1,66 +0,0 @@ -// ////////////////////////////////////// -// toggle2.c -// Toggles P9_14 and P9_16 pins as fast as it can. -// P9_14 and P9_16 are both on chip 1 so they can be toggled together. -// P9_14 is line 18 P9_16 is line 18. -// Wiring: Attach an oscilloscope to P9_14 and P9_16 to see the squarewave or -// uncomment the usleep and attach an LED. -// Setup: sudo apt uupdate; sudo apt install libgpiod-dev -// See: https://github.com/starnight/libgpiod-example/blob/master/libgpiod-led/main.c -// ////////////////////////////////////// -#include <gpiod.h> -#include <stdio.h> -#include <unistd.h> - -#define CONSUMER "Consumer" -#define NUMLINES 2 - -int main(int argc, char **argv) -{ - int chipnumber = 1; - unsigned int line_num[NUMLINES] = {18, 19}; // GPIO Pins P9_14 and P9_16 - unsigned int val; - struct gpiod_chip *chip; - struct gpiod_line_bulk line[NUMLINES]; - int i, ret; - - chip = gpiod_chip_open_by_number(chipnumber); - if (!chip) { - perror("Open chip failed\n"); - goto end; - } - - int err = gpiod_chip_get_lines(chip, line_num, NUMLINES, line); - if (err) { - perror("Get line failed\n"); - goto close_chip; - } - - int off_values[NUMLINES] = {0, 0}; - int on_values[NUMLINES] = {1, 1}; - ret = gpiod_line_request_bulk_output(line, CONSUMER, off_values); - if (ret < 0) { - perror("Request line as output failed\n"); - goto release_line; - } - - /* Blink */ - val = 0; - while(1) { - ret = gpiod_line_set_value_bulk(line, val ? on_values : off_values); - if (ret < 0) { - perror("Set line output failed\n"); - goto release_line; - } - // printf("Output %u on line #%u\n", val, line_num); - usleep(100000); - val = !val; - } - -release_line: - gpiod_line_release_bulk(line); -close_chip: - gpiod_chip_close(chip); -end: - return 0; -} diff --git a/books/beaglebone-cookbook/02sensors/code/gpiod/toggle2.py b/books/beaglebone-cookbook/02sensors/code/gpiod/toggle2.py deleted file mode 100755 index 1e7badc2..00000000 --- a/books/beaglebone-cookbook/02sensors/code/gpiod/toggle2.py +++ /dev/null @@ -1,28 +0,0 @@ -#!/usr/bin/env python3 -# ////////////////////////////////////// -# toggle2.py -# Toggles P9_14 and P9_16 pins as fast as it can. -# P9_14 and P9_16 are both on chip 1 so they can be toggled together. -# P9_14 is line 18 P9_16 is line 19. -# Wiring: Attach an oscilloscope to P9_14 and P9_16 to see the squarewave or -# uncomment the sleep and attach an LED. -# Setup: sudo apt update; pip install gpiod -# See: https://git.kernel.org/pub/scm/libs/libgpiod/libgpiod.git/tree/bindings/python/examples -# ////////////////////////////////////// - -import gpiod -import time - -LED_CHIP = 'gpiochip1' -LED_LINE_OFFSET = [18, 19] # P9_14 and P9_16 - -chip = gpiod.Chip(LED_CHIP) - -lines = chip.get_lines(LED_LINE_OFFSET) -lines.request(consumer='blink', type=gpiod.LINE_REQ_DIR_OUT) - -while True: - lines.set_values([0, 0]) - time.sleep(0.1) - lines.set_values([1, 1]) - time.sleep(0.1) diff --git a/books/beaglebone-cookbook/02sensors/code/gpiod/toggleLED.c b/books/beaglebone-cookbook/02sensors/code/gpiod/toggleLED.c deleted file mode 100644 index cc79b49b..00000000 --- a/books/beaglebone-cookbook/02sensors/code/gpiod/toggleLED.c +++ /dev/null @@ -1,66 +0,0 @@ -// ////////////////////////////////////// -// toggle2.c -// Toggles P9_14 and P9_16 pins as fast as it can. -// P9_14 and P9_16 are both on chip 1 so they can be toggled together. -// P9_14 is line 18 P9_16 is line 18. -// Wiring: Attach an oscilloscope to P9_14 and P9_16 to see the squarewave or -// uncomment the usleep and attach an LED. -// Setup: sudo apt uupdate; sudo apt install libgpiod-dev -// See: https://github.com/starnight/libgpiod-example/blob/master/libgpiod-led/main.c -// ////////////////////////////////////// -#include <gpiod.h> -#include <stdio.h> -#include <unistd.h> - -#define CONSUMER "Consumer" -#define NUMLINES 4 - -int main(int argc, char **argv) -{ - int chipnumber = 1; - unsigned int line_num[NUMLINES] = {21, 22, 23, 24}; // USR LEDS 1-4 - unsigned int val; - struct gpiod_chip *chip; - struct gpiod_line_bulk line[NUMLINES]; - int i, ret; - - chip = gpiod_chip_open_by_number(chipnumber); - if (!chip) { - perror("Open chip failed\n"); - goto end; - } - - int err = gpiod_chip_get_lines(chip, line_num, NUMLINES, line); - if (err) { - perror("Get line failed\n"); - goto close_chip; - } - - int off_values[NUMLINES] = {0, 0, 0, 0}; - int on_values[NUMLINES] = {1, 1, 1 ,1} ; - ret = gpiod_line_request_bulk_output(line, CONSUMER, off_values); - if (ret < 0) { - perror("Request line as output failed\n"); - goto release_line; - } - - /* Blink */ - val = 0; - while(1) { - ret = gpiod_line_set_value_bulk(line, val ? on_values : off_values); - if (ret < 0) { - perror("Set line output failed\n"); - goto release_line; - } - // printf("Output %u on line #%u\n", val, line_num); - usleep(100000); - val = !val; - } - -release_line: - gpiod_line_release_bulk(line); -close_chip: - gpiod_chip_close(chip); -end: - return 0; -} diff --git a/books/beaglebone-cookbook/02sensors/code/gpiod/toggleLED.py b/books/beaglebone-cookbook/02sensors/code/gpiod/toggleLED.py deleted file mode 100755 index ffca05a5..00000000 --- a/books/beaglebone-cookbook/02sensors/code/gpiod/toggleLED.py +++ /dev/null @@ -1,24 +0,0 @@ -#!/usr/bin/env python3 -# ////////////////////////////////////// -# toggleLED.py -# Toggles the four built in USR LEDs -# They are all on chip 1 so they can be toggled together. -# Setup: sudo apt uupdate; pip3 install gpiod -# See: https://git.kernel.org/pub/scm/libs/libgpiod/libgpiod.git/tree/bindings/python/examples -# ////////////////////////////////////// -import gpiod -import time - -LED_CHIP = 'gpiochip1' -LED_LINE_OFFSET = [21, 22, 23, 24] # USR LEDS 1-4 - -chip = gpiod.Chip(LED_CHIP) - -lines = chip.get_lines(LED_LINE_OFFSET) -lines.request(consumer='blink LEDs', type=gpiod.LINE_REQ_DIR_OUT) - -while True: - lines.set_values([0, 0, 0, 0]) - time.sleep(0.25) - lines.set_values([1, 1, 1, 1]) - time.sleep(0.25) diff --git a/books/beaglebone-cookbook/02sensors/code/hc-sr04-ultraSonic.js b/books/beaglebone-cookbook/02sensors/code/hc-sr04-ultraSonic.js deleted file mode 100755 index 8d1592e5..00000000 --- a/books/beaglebone-cookbook/02sensors/code/hc-sr04-ultraSonic.js +++ /dev/null @@ -1,51 +0,0 @@ -#!/usr/bin/env node - -// This is an example of reading HC-SR04 Ultrasonic Range Finder -// This version measures from the fall of the Trigger pulse -// to the end of the Echo pulse - -var b = require('bonescript'); - -var trigger = 'P9_16', // Pin to trigger the ultrasonic pulse - echo = 'P9_41', // Pin to measure to pulse width related to the distance - ms = 250; // Trigger period in ms - -var startTime, pulseTime; - -b.pinMode(echo, b.INPUT, 7, 'pulldown', 'fast', doAttach); -function doAttach(x) { - if(x.err) { - console.log('x.err = ' + x.err); - return; - } - // Call pingEnd when the pulse ends - b.attachInterrupt(echo, true, b.FALLING, pingEnd); -} - -b.pinMode(trigger, b.OUTPUT); - -b.digitalWrite(trigger, 1); // Unit triggers on a falling edge. - // Set trigger to high so we call pull it low later - -// Pull the trigger low at a regular interval. -setInterval(ping, ms); - -// Pull trigger low and start timing. -function ping() { - // console.log('ping'); - b.digitalWrite(trigger, 0); - startTime = process.hrtime(); -} - -// Compute the total time and get ready to trigger again. -function pingEnd(x) { - if(x.attached) { - console.log("Interrupt handler attached"); - return; - } - if(startTime) { - pulseTime = process.hrtime(startTime); - b.digitalWrite(trigger, 1); - console.log('pulseTime = ' + (pulseTime[1]/1000000-0.8).toFixed(3)); - } -} diff --git a/books/beaglebone-cookbook/02sensors/code/i2c-scan.js b/books/beaglebone-cookbook/02sensors/code/i2c-scan.js deleted file mode 100755 index 245a8386..00000000 --- a/books/beaglebone-cookbook/02sensors/code/i2c-scan.js +++ /dev/null @@ -1,19 +0,0 @@ -#!/usr/bin/env node -// Not working as for 28-Mar-2014 -var b = require('bonescript'); -var port = '/dev/i2c-2' - -b.i2cOpen(port, null, {}, onI2C); - -function onI2C(x) { - console.log('onI2C: ' + JSON.stringify(x)); - if (x.event == 'return') { - b.i2cScan(port, onScan); - } -} - -function onScan(x) { - if (x.event == 'callback') { - console.log('scan data: ' + JSON.stringify(x)); - } -} diff --git a/books/beaglebone-cookbook/02sensors/code/i2c-test.js b/books/beaglebone-cookbook/02sensors/code/i2c-test.js deleted file mode 100755 index 183e1f5a..00000000 --- a/books/beaglebone-cookbook/02sensors/code/i2c-test.js +++ /dev/null @@ -1,29 +0,0 @@ -#!/usr/bin/env node -# This uses the i2c method from npm what bonescript builds on -var i2c = require('i2c'); -var address = 0x49; -var wire = new i2c(address, {device: '/dev/i2c-1', debug: false}); // point to your i2c address, debug provides REPL interface - -wire.scan(function(err, data) { - // result contains an array of addresses - console.log(data); -}); - -// wire.writeByte(byte, function(err) {}); - -// wire.writeBytes(command, [byte0, byte1], function(err) {}); - -wire.readByte(function(err, res) { // result is single byte }) - console.log(err); - console.log(res); -}); - -// wire.readBytes(command, length, function(err, res) { -// // result contains a buffer of bytes -// }); - -// wire.on('data', function(data) { -// // result for continuous stream contains data buffer, address, length, timestamp -// }); - -// wire.stream(command, length, delay); // continuous stream, delay in ms diff --git a/books/beaglebone-cookbook/02sensors/code/i2cTemp.js b/books/beaglebone-cookbook/02sensors/code/i2cTemp.js deleted file mode 100755 index 9839340c..00000000 --- a/books/beaglebone-cookbook/02sensors/code/i2cTemp.js +++ /dev/null @@ -1,22 +0,0 @@ -#!/usr/bin/env node -//////////////////////////////////////// -// i2cTemp.js -// Read at TMP101 sensor on i2c bus 2, address 0x49 -// Wiring: Attach to i2c as shown in text. -// Setup: echo tmp101 0x49 > /sys/class/i2c-adapter/i2c-2/new_device -// See: -//////////////////////////////////////// -const fs = require("fs"); - -const ms = 1000; // Read time in ms -const bus = '2'; -const addr = '49'; -I2CPATH='/sys/class/i2c-adapter/i2c-'+bus+'/'+bus+'-00'+addr+'/hwmon/hwmon0'; - -// Read every ms -setInterval(readTMP, ms); - -function readTMP() { - var data = fs.readFileSync(I2CPATH+"/temp1_input").slice(0, -1); - console.log('data (C) = ' + data/1000); - } diff --git a/books/beaglebone-cookbook/02sensors/code/i2cTemp.py b/books/beaglebone-cookbook/02sensors/code/i2cTemp.py deleted file mode 100755 index 2649262f..00000000 --- a/books/beaglebone-cookbook/02sensors/code/i2cTemp.py +++ /dev/null @@ -1,22 +0,0 @@ -#!/usr/bin/env python -# //////////////////////////////////////// -# // i2cTemp.py -# // Read a TMP101 sensor on i2c bus 2, address 0x49 -# // Wiring: Attach to i2c as shown in text. -# // Setup: echo tmp101 0x49 > /sys/class/i2c-adapter/i2c-2/new_device -# // See: -# //////////////////////////////////////// -import time - -ms = 1000 # Read time in ms -bus = '2' -addr = '49' -I2CPATH='/sys/class/i2c-adapter/i2c-'+bus+'/'+bus+'-00'+addr+'/hwmon/hwmon0'; - -f = open(I2CPATH+"/temp1_input", "r") - -while True: - f.seek(0) - data = f.read()[:-1] # returns mili-degrees C - print("data (C) = " + str(int(data)/1000)) - time.sleep(ms/1000) \ No newline at end of file diff --git a/books/beaglebone-cookbook/02sensors/code/i2ctmp101.py b/books/beaglebone-cookbook/02sensors/code/i2ctmp101.py deleted file mode 100755 index 21b29fce..00000000 --- a/books/beaglebone-cookbook/02sensors/code/i2ctmp101.py +++ /dev/null @@ -1,19 +0,0 @@ -#!/usr/bin/env python -# //////////////////////////////////////// -# // i2ctmp101.py -# // Read at TMP101 sensor on i2c bus 2, address 0x49 -# // Wiring: Attach to i2c as shown in text. -# // Setup: pip install smbus -# // See: -# //////////////////////////////////////// -import smbus -import time - -ms = 1000 # Read time in ms -bus = smbus.SMBus(2) # Using i2c bus 2 -addr = 0x49 # TMP101 is at address 0x49 - -while True: - data = bus.read_byte_data(addr, 0) - print("temp (C) = " + str(data)) - time.sleep(ms/1000) diff --git a/books/beaglebone-cookbook/02sensors/code/pushbutton.js b/books/beaglebone-cookbook/02sensors/code/pushbutton.js deleted file mode 100755 index 4c852c27..00000000 --- a/books/beaglebone-cookbook/02sensors/code/pushbutton.js +++ /dev/null @@ -1,28 +0,0 @@ -#!/usr/bin/env node -//////////////////////////////////////// -// pushbutton.js -// Reads P9_42 and prints its value. -// Wiring: Connect a switch between P9_42 and 3.3V -// Setup: -// See: -//////////////////////////////////////// -const fs = require("fs"); - -const ms = 500 // Read time in ms -const pin = '7'; // P9_42 is gpio 7 -const GPIOPATH="/sys/class/gpio/"; - -// Make sure pin is exported -if(!fs.existsSync(GPIOPATH+"gpio"+pin)) { - fs.writeFileSync(GPIOPATH+"export", pin); -} -// Make it an input pin -fs.writeFileSync(GPIOPATH+"gpio"+pin+"/direction", "in"); - -// Read every ms -setInterval(readPin, ms); - -function readPin() { - var data = fs.readFileSync(GPIOPATH+"gpio"+pin+"/value").slice(0, -1); - console.log('data = ' + data); - } diff --git a/books/beaglebone-cookbook/02sensors/code/pushbutton.py b/books/beaglebone-cookbook/02sensors/code/pushbutton.py deleted file mode 100755 index 2bb13385..00000000 --- a/books/beaglebone-cookbook/02sensors/code/pushbutton.py +++ /dev/null @@ -1,33 +0,0 @@ -#!/usr/bin/env python -# //////////////////////////////////////// -# // pushbutton.py -# // Reads P9_42 and prints its value. -# // Wiring: Connect a switch between P9_42 and 3.3V -# // Setup: -# // See: -# //////////////////////////////////////// -import time -import os - -ms = 500 # Read time in ms -pin = '7' # P9_42 is gpio 7 -GPIOPATH="/sys/class/gpio" - -# Make sure pin is exported -if (not os.path.exists(GPIOPATH+"/gpio"+pin)): - f = open(GPIOPATH+"/export", "w") - f.write(pin) - f.close() - -# Make it an input pin -f = open(GPIOPATH+"/gpio"+pin+"/direction", "w") -f.write("in") -f.close() - -f = open(GPIOPATH+"/gpio"+pin+"/value", "r") - -while True: - f.seek(0) - data = f.read()[:-1] - print("data = " + data) - time.sleep(ms/1000) diff --git a/books/beaglebone-cookbook/02sensors/code/pushbutton2.js b/books/beaglebone-cookbook/02sensors/code/pushbutton2.js deleted file mode 100755 index f54307a5..00000000 --- a/books/beaglebone-cookbook/02sensors/code/pushbutton2.js +++ /dev/null @@ -1,10 +0,0 @@ -#!/usr/bin/env node -var b = require('bonescript'); -var button = 'P9_42'; -var state; // State of pushbutton - -b.pinMode(button, b.INPUT, 7, 'pulldown'); - -state = b.digitalRead(button); -console.log('button state = ' + state); - diff --git a/books/beaglebone-cookbook/02sensors/code/pushbuttonPullup.js b/books/beaglebone-cookbook/02sensors/code/pushbuttonPullup.js deleted file mode 100755 index bee1ce82..00000000 --- a/books/beaglebone-cookbook/02sensors/code/pushbuttonPullup.js +++ /dev/null @@ -1,34 +0,0 @@ -#!/usr/bin/env node -var b = require('bonescript'); -var buttonTop = 'P9_26'; - -b.pinMode(buttonTop, b.INPUT, 7, 'pullup', 'fast', doAttachTop); - -function doAttachTop(x) { - if(x.err) { - console.log('x.err = ' + x.err); - return; - } - b.attachInterrupt(buttonTop, true, b.CHANGE, printStatus); -} - -var buttonBot = 'P9_42'; -b.pinMode(buttonBot, b.INPUT, 7, 'pulldown', 'fast', doAttachBot); - -function doAttachBot(x) { - if(x.err) { - console.log('x.err = ' + x.err); - return; - } - b.attachInterrupt(buttonBot, true, b.CHANGE, printStatus); -} - -function printStatus(x) { - if(x.attached) { - console.log("Interrupt handler attached"); - return; - } - - console.log('x.value = ' + x.value); - console.log('x.err = ' + x.err); -} diff --git a/books/beaglebone-cookbook/02sensors/code/pushbutton_digitalRead.js b/books/beaglebone-cookbook/02sensors/code/pushbutton_digitalRead.js deleted file mode 100755 index 59f1f14d..00000000 --- a/books/beaglebone-cookbook/02sensors/code/pushbutton_digitalRead.js +++ /dev/null @@ -1,11 +0,0 @@ -#!/usr/bin/env node -var b = require('bonescript'); -var button = 'P9_42'; - -b.pinMode(button, b.INPUT, 7, 'pulldown'); -b.digitalRead(button, printStatus); - -function printStatus(x) { - console.log('x.value = ' + x.value); - console.log('x.err = ' + x.err); -} diff --git a/books/beaglebone-cookbook/02sensors/code/rotaryEncoder.js b/books/beaglebone-cookbook/02sensors/code/rotaryEncoder.js deleted file mode 100755 index 3390a817..00000000 --- a/books/beaglebone-cookbook/02sensors/code/rotaryEncoder.js +++ /dev/null @@ -1,39 +0,0 @@ -#!/usr/bin/env node -// This uses the eQEP hardware to read a rotary encoder -// bone$ config-pin P8_11 eqep -// bone$ config-pin P8_12 eqep -const fs = require("fs"); - -const eQEP = "2"; -const COUNTERPATH = '/dev/bone/counter/counter'+eQEP+'/count0'; - -const ms = 100; // Time between samples in ms -const maxCount = '1000000'; - -// Set the eEQP maximum count -fs.writeFileSync(COUNTERPATH+'/ceiling', maxCount); - -// Enable -fs.writeFileSync(COUNTERPATH+'/enable', '1'); - -setInterval(readEncoder, ms); // Check state every ms - -var olddata = -1; -function readEncoder() { - var data = parseInt(fs.readFileSync(COUNTERPATH+'/count')); - if(data != olddata) { - // Print only if data changes - console.log('data = ' + data); - olddata = data; - } -} - -// Black OR Pocket -// eQEP0: P9.27 and P9.42 OR P1_33 and P2_34 -// eQEP1: P9.33 and P9.35 -// eQEP2: P8.11 and P8.12 OR P2_24 and P2_33 - -// AI -// eQEP1: P8.33 and P8.35 -// eQEP2: P8.11 and P8.12 or P9.19 and P9.41 -// eQEP3: P8.24 abd P8.25 or P9.27 and P9.42 \ No newline at end of file diff --git a/books/beaglebone-cookbook/02sensors/code/rotaryEncoder.py b/books/beaglebone-cookbook/02sensors/code/rotaryEncoder.py deleted file mode 100755 index 04eb3735..00000000 --- a/books/beaglebone-cookbook/02sensors/code/rotaryEncoder.py +++ /dev/null @@ -1,43 +0,0 @@ -#!/usr/bin/env python -# // This uses the eQEP hardware to read a rotary encoder -# // bone$ config-pin P8_11 eqep -# // bone$ config-pin P8_12 eqep -import time - -eQEP = '2' -COUNTERPATH = '/dev/bone/counter/counter'+eQEP+'/count0' - -ms = 100 # Time between samples in ms -maxCount = '1000000' - -# Set the eEQP maximum count -f = open(COUNTERPATH+'/ceiling', 'w') -f.write(maxCount) -f.close() - -# Enable -f = open(COUNTERPATH+'/enable', 'w') -f.write('1') -f.close() - -f = open(COUNTERPATH+'/count', 'r') - -olddata = -1 -while True: - f.seek(0) - data = f.read()[:-1] - # Print only if data changes - if data != olddata: - olddata = data - print("data = " + data) - time.sleep(ms/1000) - -# Black OR Pocket -# eQEP0: P9.27 and P9.42 OR P1_33 and P2_34 -# eQEP1: P9.33 and P9.35 -# eQEP2: P8.11 and P8.12 OR P2_24 and P2_33 - -# AI -# eQEP1: P8.33 and P8.35 -# eQEP2: P8.11 and P8.12 or P9.19 and P9.41 -# eQEP3: P8.24 abd P8.25 or P9.27 and P9.42 \ No newline at end of file diff --git a/books/beaglebone-cookbook/02sensors/code/sensorTag.js b/books/beaglebone-cookbook/02sensors/code/sensorTag.js deleted file mode 100755 index 9b3eed15..00000000 --- a/books/beaglebone-cookbook/02sensors/code/sensorTag.js +++ /dev/null @@ -1,103 +0,0 @@ -#!/usr/bin/env node -// From: https://github.com/sandeepmistry/node-sensortag - -// Reads temperature - -var util = require('util'); // <1> -var async = require('async'); -var SensorTag = require('sensortag'); -var fs = require('fs'); - -console.log("Be sure sensorTag is on"); - -SensorTag.discover(function(sensorTag) { // <2> - console.log('sensorTag = ' + sensorTag); - sensorTag.on('disconnect', function() { // <3> - console.log('disconnected!'); - process.exit(0); - }); - - async.series([ // <4> - function(callback) { - console.log('connect'); // <5> - sensorTag.connect(callback); - }, - function(callback) { // <6> - console.log('discoverServicesAndCharacteristics'); - sensorTag.discoverServicesAndCharacteristics(callback); - }, - function(callback) { - console.log('enableIrTemperature'); // <7> - sensorTag.enableIrTemperature(callback); - }, - function(callback) { - setTimeout(callback, 100); // <8> - }, - function(callback) { - console.log('readIrTemperature'); // <9> - sensorTag.readIrTemperature( - function(objectTemperature, ambientTemperature) { - console.log('\tobject temperature = %d °C', - objectTemperature.toFixed(1)); - console.log('\tambient temperature = %d °C', - ambientTemperature.toFixed(1)); - callback(); - }); - - sensorTag.on('irTemperatureChange', // <10> - function(objectTemperature, ambientTemperature) { - console.log('\tobject temperature = %d °C', - objectTemperature.toFixed(1)); - console.log('\tambient temperature = %d °C\n', - ambientTemperature.toFixed(1)); - }); - - sensorTag.notifyIrTemperature(function() { - console.log('notifyIrTemperature'); - }); - }, - // function(callback) { - // console.log('disableIrTemperature'); // <11> - // sensorTag.disableIrTemperature(callback); - // }, - - function(callback) { - console.log('readSimpleRead'); // <12> - sensorTag.on('simpleKeyChange', function(left, right) { - console.log('left: ' + left + ' right: ' + right); - if (left && right) { - sensorTag.notifySimpleKey(callback); // <13> - } - }); - - sensorTag.notifySimpleKey(function() { // <14> - }); - }, - function(callback) { - console.log('disconnect'); - sensorTag.disconnect(callback); // <15> - } - ] - ); -}); - -// The MIT License (MIT) - -// Copyright (c) 2013 Sandeep Mistry - -// 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. diff --git a/books/beaglebone-cookbook/02sensors/code/stop.js b/books/beaglebone-cookbook/02sensors/code/stop.js deleted file mode 100755 index 0c3ec1b6..00000000 --- a/books/beaglebone-cookbook/02sensors/code/stop.js +++ /dev/null @@ -1,10 +0,0 @@ -#!/usr/bin/env node -// Used for turning everything off. -var b = require('bonescript'); -var gpio = ['P9_11', 'P9_13', 'P9_15', 'P9_16', 'P9_21']; -var i; - -for(i=0; i<gpio.length; i++) { - b.pinMode(gpio[i], b.OUTPUT); - b.digitalWrite(gpio[i], b.LOW); -} diff --git a/books/beaglebone-cookbook/02sensors/code/testHC-SR04.js b/books/beaglebone-cookbook/02sensors/code/testHC-SR04.js deleted file mode 100755 index 452fd8af..00000000 --- a/books/beaglebone-cookbook/02sensors/code/testHC-SR04.js +++ /dev/null @@ -1,37 +0,0 @@ -#!/usr/bin/env node - -// This is an example of reading HC-SR04 Ultrasonic Range Finder - -var b = require('bonescript'); - -var motor = 'P9_16',// Pin to drive transistor - range = 'P9_41', - min = 0.05, // Slowest speed (duty cycle) - max = 1, // Fastest (always on) - ms = 100, // How often to change speed, in ms - width = 10, // Pulse width in us - freq = 100, // Frequency in Hz - step = 0.05; // Change in speed - -b.pinMode(range, b.INPUT); // Make sure there is on pull-up/down -b.pinMode(motor, b.ANALOG_OUTPUT); -var dutyCycle = width/1000000*freq; -b.analogWrite(motor, dutyCycle, freq); - - -// var timer = setInterval(sweep, ms); - -// function sweep() { -// speed += step; -// if(speed > max || speed < min) { -// step *= -1; -// } -// b.analogWrite(motor, speed); -// console.log('speed = ' + speed); -// } - -process.on('SIGINT', function() { - console.log('Got SIGINT, turning motor off'); - clearInterval(timer); // Stop the timer - b.analogWrite(motor, 0); // Turn motor off -}); \ No newline at end of file diff --git a/books/beaglebone-cookbook/02sensors/code/ultrasonicRange.js b/books/beaglebone-cookbook/02sensors/code/ultrasonicRange.js deleted file mode 100755 index 0d00de89..00000000 --- a/books/beaglebone-cookbook/02sensors/code/ultrasonicRange.js +++ /dev/null @@ -1,30 +0,0 @@ -#!/usr/bin/env node -////////////////////////////////////// -// ultrasonicRange.js -// Reads the analog value of the sensor. -////////////////////////////////////// -const fs = require("fs"); -const ms = 250; // Time in milliseconds - -const pin = "0"; // sensor, A0, P9_39 - -const IIOPATH='/sys/bus/iio/devices/iio:device0/in_voltage'+pin+'_raw'; - -console.log('Hit ^C to stop'); - -// Read every ms -setInterval(readPin, ms); - -function readPin() { - var data = fs.readFileSync(IIOPATH); - console.log('data= ' + data); - } -// Bone | Pocket | AIN -// ----- | ------ | --- -// P9_39 | P1_19 | 0 -// P9_40 | P1_21 | 1 -// P9_37 | P1_23 | 2 -// P9_38 | P1_25 | 3 -// P9_33 | P1_27 | 4 -// P9_36 | P2_35 | 5 -// P9_35 | P1_02 | 6 diff --git a/books/beaglebone-cookbook/02sensors/code/ultrasonicRange.py b/books/beaglebone-cookbook/02sensors/code/ultrasonicRange.py deleted file mode 100755 index d02bf751..00000000 --- a/books/beaglebone-cookbook/02sensors/code/ultrasonicRange.py +++ /dev/null @@ -1,30 +0,0 @@ -#!/usr/bin/env python -# ////////////////////////////////////// -# // ultrasonicRange.js -# // Reads the analog value of the sensor. -# ////////////////////////////////////// -import time -ms = 250; # Time in milliseconds - -pin = "0" # sensor, A0, P9_39 - -IIOPATH='/sys/bus/iio/devices/iio:device0/in_voltage'+pin+'_raw' - -print('Hit ^C to stop'); - -f = open(IIOPATH, "r") -while True: - f.seek(0) - data = f.read()[:-1] - print('data= ' + data) - time.sleep(ms/1000) - -# // Bone | Pocket | AIN -# // ----- | ------ | --- -# // P9_39 | P1_19 | 0 -# // P9_40 | P1_21 | 1 -# // P9_37 | P1_23 | 2 -# // P9_38 | P1_25 | 3 -# // P9_33 | P1_27 | 4 -# // P9_36 | P2_35 | 5 -# // P9_35 | P1_02 | 6 diff --git a/books/beaglebone-cookbook/02sensors/code/w1.js b/books/beaglebone-cookbook/02sensors/code/w1.js deleted file mode 100755 index 187023af..00000000 --- a/books/beaglebone-cookbook/02sensors/code/w1.js +++ /dev/null @@ -1,23 +0,0 @@ -#!/usr/bin/env node -//////////////////////////////////////// -// w1.js -// Read a Dallas 1-wire device on P9_12 -// Wiring: Attach gnd and 3.3V and data to P9_12 -// Setup: Edit /boot/uEnv.txt to include: -// uboot_overlay_addr4=BB-W1-P9.12-00A0.dtbo -// See: -//////////////////////////////////////// -const fs = require("fs"); - -const ms = 500 // Read time in ms -// Do ls /sys/bus/w1/devices and find the address of your device -const addr = '28-00000d459c2c'; // Must be changed for your device. -const W1PATH ='/sys/bus/w1/devices/' + addr; - -// Read every ms -setInterval(readW1, ms); - -function readW1() { - var data = fs.readFileSync(W1PATH+'/temperature').slice(0, -1); - console.log('temp (C) = ' + data/1000); - } diff --git a/books/beaglebone-cookbook/02sensors/code/w1.py b/books/beaglebone-cookbook/02sensors/code/w1.py deleted file mode 100755 index 8a0a62f6..00000000 --- a/books/beaglebone-cookbook/02sensors/code/w1.py +++ /dev/null @@ -1,23 +0,0 @@ -#!/usr/bin/env python -# //////////////////////////////////////// -# // w1.js -# // Read a Dallas 1-wire device on P9_12 -# // Wiring: Attach gnd and 3.3V and data to P9_12 -# // Setup: Edit /boot/uEnv.txt to include: -# // uboot_overlay_addr4=BB-W1-P9.12-00A0.dtbo -# // See: -# //////////////////////////////////////// -import time - -ms = 500 # Read time in ms -# Do ls /sys/bus/w1/devices and find the address of your device -addr = '28-00000d459c2c' # Must be changed for your device. -W1PATH ='/sys/bus/w1/devices/' + addr - -f = open(W1PATH+'/temperature') - -while True: - f.seek(0) - data = f.read()[:-1] - print("temp (C) = " + str(int(data)/1000)) - time.sleep(ms/1000) diff --git a/books/beaglebone-cookbook/02sensors/sensors.rst b/books/beaglebone-cookbook/02sensors/sensors.rst index 6f15d0ad..46453b38 100644 --- a/books/beaglebone-cookbook/02sensors/sensors.rst +++ b/books/beaglebone-cookbook/02sensors/sensors.rst @@ -91,7 +91,7 @@ You are just a few simple steps from running any of the recipes in this book. .. code-block:: bash bone$ cd - bone$ cd BoneCookbook/docs/02sensors/code + bone$ cd beaglebone-cookbook-code/02sensors .. _sensors_vsc_bash: @@ -168,11 +168,11 @@ reads GPIO port *P9_42*, which is attached to the pushbutton. .. _py_pushbutton_code: -.. literalinclude:: code/pushbutton.py +.. literalinclude:: ../code/02sensors/pushbutton.py :caption: Monitoring a pushbutton (pushbutton.py) :linenos: -:download:`pushbutton.py <code/pushbutton.py>` +:download:`pushbutton.py <../code/02sensors/pushbutton.py>` .. _js_pushbutton_code: @@ -180,7 +180,7 @@ reads GPIO port *P9_42*, which is attached to the pushbutton. :caption: Monitoring a pushbutton (pushbutton.js) :linenos: -:download:`pushbutton.js <code/pushbutton.js>` +:download:`pushbutton.js <../code/02sensors/pushbutton.js>` Put this code in a file called *pushbutton.js* following the steps in :ref:`sensors_getting_started`. In the VSC *bash* tab, run it by using the following commands: @@ -298,15 +298,15 @@ Add the code to a file called _analogIn.js_ and run it; then change the resistor :caption: Reading an analog voltage (analogIn.py) :linenos: -:download:`analogIn.py <code/analogIn.py>` +:download:`analogIn.py <../code/02sensors/analogIn.py>` .. _sensors_analogIn_code: -.. literalinclude:: code/analogIn.js +.. literalinclude:: ../code/02sensors/analogIn.js :caption: Reading an analog voltage (analogIn.js) :linenos: -:download:`analogIn.js <code/analogIn.js>` +:download:`analogIn.js <../code/02sensors/analogIn.js>` .. note:: @@ -370,20 +370,20 @@ shows the code that reads the sensor at a fixed interval. .. _py_ultrasonicRange_code: -.. literalinclude:: code/ultrasonicRange.py +.. literalinclude:: ../code/02sensors/ultrasonicRange.py :caption: Reading an analog voltage (ultrasonicRange.py) :linenos: -:download:`ultrasonicRange.py <code/ultrasonicRange.py>` +:download:`ultrasonicRange.py <../code/02sensors/ultrasonicRange.py>` .. _sensors_ultrasonicRange_code: -.. literalinclude:: code/ultrasonicRange.js +.. literalinclude:: ../code/02sensors/ultrasonicRange.js :caption: Reading an analog voltage (ultrasonicRange.js) :linenos: -:download:`ultrasonicRange.js <code/ultrasonicRange.js>` +:download:`ultrasonicRange.js <../code/02sensors/ultrasonicRange.js>` .. _sensors_hc-sr04: @@ -433,11 +433,11 @@ HC-SR04 to the Bone's 5 V power supply. .. _sensors_hc-sr04_code: -.. literalinclude:: code/hc-sr04-ultraSonic.js +.. literalinclude:: ../code/02sensors/hc-sr04-ultraSonic.js :caption: Driving a HC-SR04 ultrasound sensor (hc-sr04-ultraSonic.js) :linenos: -:download:`hc-sr04-ultraSonic.js <code/hc-sr04-ultraSonic.js>` +:download:`hc-sr04-ultraSonic.js <../code/02sensors/hc-sr04-ultraSonic.js>` This code is more complex than others in this chapter, because we have to tell the device when to start @@ -520,19 +520,19 @@ to a file named *rotaryEncoder.js* and run it. .. _digital_rotaryEncoder_py: -.. literalinclude:: code/rotaryEncoder.py +.. literalinclude:: ../code/02sensors/rotaryEncoder.py :caption: Reading a rotary encoder (rotaryEncoder.py) :linenos: -:download:`rotaryEncoder.py <code/rotaryEncoder.py>` +:download:`rotaryEncoder.py <../code/02sensors/rotaryEncoder.py>` .. _digital_rotaryEncoder_js: -.. literalinclude:: code/rotaryEncoder.js +.. literalinclude:: ../code/02sensors/rotaryEncoder.js :caption: Reading a rotary encoder (rotaryEncoder.js) :linenos: -:download:`rotaryEncoder.js <code/rotaryEncoder.js>` +:download:`rotaryEncoder.js <../code/02sensors/rotaryEncoder.js>` Try rotating the encoder clockwise and counter-clockwise. You'll see an output like this: @@ -608,11 +608,11 @@ will print the current location every time the GPS outputs it. .. _digital_GPS_code: -.. literalinclude:: code/GPS.js +.. literalinclude:: ../code/02sensors/GPS.js :caption: Talking to a GPS with UART 4 (GPS.js) :linenos: -:download:`GPS.js <code/GPS.js>` +:download:`GPS.js <../code/02sensors/GPS.js>` If you don't need the NMEA formatting, you can skip the *npm* part and remove the lines in the code that refer to it. @@ -786,19 +786,19 @@ Once the driver is in place, you can read it via code. .. _py_i2cTemp_code: -.. literalinclude:: code/i2cTemp.py +.. literalinclude:: ../code/02sensors/i2cTemp.py :caption: Reading an |I2C| device (i2cTemp.py) :linenos: -:download:`i2cTemp.py <code/i2cTemp.py>` +:download:`i2cTemp.py <../code/02sensors/i2cTemp.py>` .. _js_i2cTemp_code: -.. literalinclude:: code/i2cTemp.js +.. literalinclude:: ../code/02sensors/i2cTemp.js :caption: Reading an |I2C| device (i2cTemp.js) :linenos: -:download:`i2cTemp.js <code/i2cTemp.js>` +:download:`i2cTemp.js <../code/02sensors/i2cTemp.js>` Run the code by using the following command: @@ -827,11 +827,11 @@ using the kernel driver. First you need to install the i2c module. .. _js_i2ctmp101_code: -.. literalinclude:: code/i2ctmp101.py +.. literalinclude:: ../code/02sensors/i2ctmp101.py :caption: Reading an |I2C| device (i2cTemp.py) :linenos: -:download:`i2ctmp101.py <code/i2ctmp101.py>` +:download:`i2ctmp101.py <../code/02sensors/i2ctmp101.py>` This gets only 8 bits for the temperature. See the TMP101 datasheet for details on how to get up to 12 bits. @@ -914,19 +914,19 @@ that the path points to your device, and then run it. .. _py_onewire__code: -.. literalinclude:: code/w1.py +.. literalinclude:: ../code/02sensors/w1.py :caption: Reading a temperature with a DS18B20 (w1.py) :linenos: -:download:`w1.py <code/w1.py>` +:download:`w1.py <../code/02sensors/w1.py>` .. _sensors_onewire__code: -.. literalinclude:: code/w1.js +.. literalinclude:: ../code/02sensors/w1.js :caption: Reading a temperature with a DS18B20 (w1.js) :linenos: -:download:`w1.js <code/w1.js>` +:download:`w1.js <../code/02sensors/w1.js>` .. code-block:: bash @@ -983,7 +983,7 @@ Each temperature sensor has a unique serial number, so you can have several all .. // [source, js] .. // ---- -.. // include::code/sensorTag.js[sensorTag.js] +.. // include::../code/02sensors/sensorTag.js[sensorTag.js] .. // ---- .. // ==== @@ -1120,11 +1120,11 @@ can change that default by creating a file in your home directory called .. _sensors_asoundrc: -.. literalinclude:: code/audio.asoundrc +.. literalinclude:: ../code/02sensors/audio.asoundrc :caption: Change the default audio out by putting this in ~/.asoundrc (audio.asoundrc) :linenos: -:download:`audio.asoundrc <code/audio.asoundrc>` +:download:`audio.asoundrc <../code/02sensors/audio.asoundrc>` You can easily play ``.wav`` files with *aplay*: diff --git a/books/beaglebone-cookbook/03displays/code/externLED.js b/books/beaglebone-cookbook/03displays/code/externLED.js deleted file mode 100755 index 40ad5dab..00000000 --- a/books/beaglebone-cookbook/03displays/code/externLED.js +++ /dev/null @@ -1,33 +0,0 @@ -#!/usr/bin/env node -//////////////////////////////////////// -// externalLED.js -// Blinks the P9_14 pin -// Wiring: -// Setup: -// See: -//////////////////////////////////////// -const fs = require("fs"); - -// Look up P9.14 using gpioinfo | grep -e chip -e P9.14. chip 1, line 18 maps to 50 -pin="50"; - -GPIOPATH="/sys/class/gpio/"; -// Make sure pin is exported -if(!fs.existsSync(GPIOPATH+"gpio"+pin)) { - fs.writeFileSync(GPIOPATH+"export", pin); -} -// Make it an output pin -fs.writeFileSync(GPIOPATH+"gpio"+pin+"/direction", "out"); - -// Blink every 500ms -setInterval(toggle, 500); - -state="1"; -function toggle() { - fs.writeFileSync(GPIOPATH+"gpio"+pin+"/value", state); - if(state == "0") { - state = "1"; - } else { - state = "0"; - } -} diff --git a/books/beaglebone-cookbook/03displays/code/externLED.py b/books/beaglebone-cookbook/03displays/code/externLED.py deleted file mode 100755 index 786d3217..00000000 --- a/books/beaglebone-cookbook/03displays/code/externLED.py +++ /dev/null @@ -1,40 +0,0 @@ -#!/usr/bin/env python -# //////////////////////////////////////// -# // externalLED.py -# // Blinks an external LED wired to P9_14. -# // Wiring: P9_14 connects to the plus lead of an LED. The negative lead of the -# LED goes to a 220 Ohm resistor. The other lead of the resistor goes -# to ground. -# // Setup: -# // See: -# //////////////////////////////////////// -import time -import os - -ms = 250 # Time to blink in ms -# Look up P9.14 using gpioinfo | grep -e chip -e P9.14. chip 1, line 18 maps to 50 -pin = '50' - -GPIOPATH='/sys/class/gpio/' -# Make sure pin is exported -if (not os.path.exists(GPIOPATH+"gpio"+pin)): - f = open(GPIOPATH+"export", "w") - f.write(pin) - f.close() - -# Make it an output pin -f = open(GPIOPATH+"gpio"+pin+"/direction", "w") -f.write("out") -f.close() - -f = open(GPIOPATH+"gpio"+pin+"/value", "w") -# Blink -while True: - f.seek(0) - f.write("1") - time.sleep(ms/1000) - - f.seek(0) - f.write("0") - time.sleep(ms/1000) -f.close() diff --git a/books/beaglebone-cookbook/03displays/code/fadeLED.js b/books/beaglebone-cookbook/03displays/code/fadeLED.js deleted file mode 100755 index 49db7ecd..00000000 --- a/books/beaglebone-cookbook/03displays/code/fadeLED.js +++ /dev/null @@ -1,44 +0,0 @@ -#!/usr/bin/env node -//////////////////////////////////////// -// fadeLED.js -// Blinks the P9_14 pin -// Wiring: -// Setup: config-pin P9_14 pwm -// See: -//////////////////////////////////////// -const fs = require("fs"); -const ms = '20'; // Fade time in ms - -const pwmPeriod = '1000000'; // Period in ns -const pwm = '1'; // pwm to use -const channel = 'a'; // channel to use -const PWMPATH='/dev/bone/pwm/'+pwm+'/'+channel; -var step = 0.02; // Step size -const min = 0.02, // dimmest value - max = 1; // brightest value -var brightness = min; // Current brightness; - - -// Set the period in ns -fs.writeFileSync(PWMPATH+'/period', pwmPeriod); -fs.writeFileSync(PWMPATH+'/duty_cycle', pwmPeriod/2); -fs.writeFileSync(PWMPATH+'/enable', '1'); - -setInterval(fade, ms); // Step every ms - -function fade() { - fs.writeFileSync(PWMPATH+'/duty_cycle', - parseInt(pwmPeriod*brightness)); - brightness += step; - if(brightness >= max || brightness <= min) { - step = -1 * step; - } -} - -// | Pin | pwm | channel -// | P9_31 | 0 | a -// | P9_29 | 0 | b -// | P9_14 | 1 | a -// | P9_16 | 1 | b -// | P8_19 | 2 | a -// | P8_13 | 2 | b \ No newline at end of file diff --git a/books/beaglebone-cookbook/03displays/code/fadeLED.py b/books/beaglebone-cookbook/03displays/code/fadeLED.py deleted file mode 100755 index bd2016d1..00000000 --- a/books/beaglebone-cookbook/03displays/code/fadeLED.py +++ /dev/null @@ -1,44 +0,0 @@ -#!/usr/bin/env python -# //////////////////////////////////////// -# // fadeLED.py -# // Blinks the P9_14 pin -# // Wiring: -# // Setup: config-pin P9_14 pwm -# // See: -# //////////////////////////////////////// -import time -ms = 20; # Fade time in ms - -pwmPeriod = 1000000 # Period in ns -pwm = '1' # pwm to use -channel = 'a' # channel to use -PWMPATH='/dev/bone/pwm/'+pwm+'/'+channel -step = 0.02 # Step size -min = 0.02 # dimmest value -max = 1 # brightest value -brightness = min # Current brightness - -f = open(PWMPATH+'/period', 'w') -f.write(str(pwmPeriod)) -f.close() - -f = open(PWMPATH+'/enable', 'w') -f.write('1') -f.close() - -f = open(PWMPATH+'/duty_cycle', 'w') -while True: - f.seek(0) - f.write(str(round(pwmPeriod*brightness))) - brightness += step - if(brightness >= max or brightness <= min): - step = -1 * step - time.sleep(ms/1000) - -# | Pin | pwm | channel -# | P9_31 | 0 | a -# | P9_29 | 0 | b -# | P9_14 | 1 | a -# | P9_16 | 1 | b -# | P8_19 | 2 | a -# | P8_13 | 2 | b \ No newline at end of file diff --git a/books/beaglebone-cookbook/03displays/code/internLED.js b/books/beaglebone-cookbook/03displays/code/internLED.js deleted file mode 100755 index b6545f21..00000000 --- a/books/beaglebone-cookbook/03displays/code/internLED.js +++ /dev/null @@ -1,25 +0,0 @@ -#!/usr/bin/env node -// ////////////////////////////////////// -// internalLED.js -// Blinks the USR LEDs. -// Wiring: -// Setup: -// See: -// ////////////////////////////////////// -const fs = require('fs'); -const ms = 250; // Blink time in ms -const LED = 'usr0'; // LED to blink -const LEDPATH = '/sys/class/leds/beaglebone:green:'+LED+'/brightness'; - -var state = '1'; // Initial state - -setInterval(flash, ms); // Change state every ms - -function flash() { - fs.writeFileSync(LEDPATH, state) - if(state === '1') { - state = '0'; - } else { - state = '1'; - } -} diff --git a/books/beaglebone-cookbook/03displays/code/internLED.py b/books/beaglebone-cookbook/03displays/code/internLED.py deleted file mode 100755 index 11db5efc..00000000 --- a/books/beaglebone-cookbook/03displays/code/internLED.py +++ /dev/null @@ -1,26 +0,0 @@ -#!/usr/bin/env python -# ////////////////////////////////////// -# internalLED.py -# Blinks A USR LED. -# Wiring: -# Setup: -# See: -# ////////////////////////////////////// -import time - -ms = 250 # Blink time in ms -LED = 'usr0'; # LED to blink -LEDPATH = '/sys/class/leds/beaglebone:green:'+LED+'/brightness' - -state = '1' # Initial state - -f = open(LEDPATH, "w") - -while True: - f.seek(0) - f.write(state) - if (state == '1'): - state = '0' - else: - state = '1' - time.sleep(ms/1000) \ No newline at end of file diff --git a/books/beaglebone-cookbook/03displays/code/matrixLEDi2c.js b/books/beaglebone-cookbook/03displays/code/matrixLEDi2c.js deleted file mode 100755 index 405419b7..00000000 --- a/books/beaglebone-cookbook/03displays/code/matrixLEDi2c.js +++ /dev/null @@ -1,45 +0,0 @@ -#!/usr/bin/env node -// npm install -g sleep - -var b = require('bonescript'); -var sleep = require('sleep'); -var port = '/dev/i2c-2' // <1> -var matrix = 0x70; // <2> -var time = 1000000; // Delay between images in us - -// The first btye is GREEN, the second is RED. <3> -var smile = - [0x00, 0x3c, 0x00, 0x42, 0x28, 0x89, 0x04, 0x85, - 0x04, 0x85, 0x28, 0x89, 0x00, 0x42, 0x00, 0x3c]; -var frown = - [0x3c, 0x00, 0x42, 0x00, 0x85, 0x20, 0x89, 0x00, - 0x89, 0x00, 0x85, 0x20, 0x42, 0x00, 0x3c, 0x00]; -var neutral = - [0x3c, 0x3c, 0x42, 0x42, 0xa9, 0xa9, 0x89, 0x89, - 0x89, 0x89, 0xa9, 0xa9, 0x42, 0x42, 0x3c, 0x3c]; -var blank = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; - -b.i2cOpen(port, matrix); // <4> - -b.i2cWriteByte(port, 0x21); // Start oscillator (p10) <5> -b.i2cWriteByte(port, 0x81); // Disp on, blink off (p11) -b.i2cWriteByte(port, 0xe7); // Full brightness (page 15) - -b.i2cWriteBytes(port, 0x00, frown); // <6> -sleep.usleep(time); - -b.i2cWriteBytes(port, 0x00, neutral); -sleep.usleep(time); - -b.i2cWriteBytes(port, 0x00, smile); -// Fade the display -var fade; -for(fade = 0xef; fade >= 0xe0; fade--) { // <7> - b.i2cWriteByte(port, fade); - sleep.usleep(time/10); -} -for(fade = 0xe1; fade <= 0xef; fade++) { - b.i2cWriteByte(port, fade); - sleep.usleep(time/10); -} -b.i2cWriteBytes(port, 0x04, [0xff]); \ No newline at end of file diff --git a/books/beaglebone-cookbook/03displays/code/matrixLEDi2c.py b/books/beaglebone-cookbook/03displays/code/matrixLEDi2c.py deleted file mode 100755 index 311714c0..00000000 --- a/books/beaglebone-cookbook/03displays/code/matrixLEDi2c.py +++ /dev/null @@ -1,41 +0,0 @@ -#!/usr/bin/env python -# //////////////////////////////////////// -# // i2cTemp.py -# // Write an 8x8 Red/Green LED matrix. -# // Wiring: Attach to i2c as shown in text. -# // Setup: echo tmp101 0x49 > /sys/class/i2c-adapter/i2c-2/new_device -# // See: https://www.adafruit.com/product/902 -# //////////////////////////////////////// -import smbus -import time - -bus = smbus.SMBus(2) # Use i2c bus 2 <1> -matrix = 0x70 # Use address 0x70 <2> -ms = 1; # Delay between images in ms - -# The first byte is GREEN, the second is RED. <3> -smile = [0x00, 0x3c, 0x00, 0x42, 0x28, 0x89, 0x04, 0x85, - 0x04, 0x85, 0x28, 0x89, 0x00, 0x42, 0x00, 0x3c -] -frown = [0x3c, 0x00, 0x42, 0x00, 0x85, 0x20, 0x89, 0x00, - 0x89, 0x00, 0x85, 0x20, 0x42, 0x00, 0x3c, 0x00 -] -neutral = [0x3c, 0x3c, 0x42, 0x42, 0xa9, 0xa9, 0x89, 0x89, - 0x89, 0x89, 0xa9, 0xa9, 0x42, 0x42, 0x3c, 0x3c -] - -bus.write_byte_data(matrix, 0x21, 0) # Start oscillator (p10) <4> -bus.write_byte_data(matrix, 0x81, 0) # Disp on, blink off (p11) -bus.write_byte_data(matrix, 0xe7, 0) # Full brightness (page 15) - -bus.write_i2c_block_data(matrix, 0, frown) # <5> -for fade in range(0xef, 0xe0, -1): # <6> - bus.write_byte_data(matrix, fade, 0) - time.sleep(ms/10) - -bus.write_i2c_block_data(matrix, 0, neutral) -for fade in range(0xe0, 0xef, 1): - bus.write_byte_data(matrix, fade, 0) - time.sleep(ms/10) - -bus.write_i2c_block_data(matrix, 0, smile) diff --git a/books/beaglebone-cookbook/03displays/code/neoPixel.sh b/books/beaglebone-cookbook/03displays/code/neoPixel.sh deleted file mode 100755 index 0e213f4b..00000000 --- a/books/beaglebone-cookbook/03displays/code/neoPixel.sh +++ /dev/null @@ -1,19 +0,0 @@ -#!/bin/sh -# Here's what you do to install the neoPixel driver -# Disable the HDMI to gain access to the PRU pins -sed -i '/cape_disable=capemgr.disable_partno=BB-BONELT-HDMI,BB-BONELT-HDMIN$/ \ - s/^#//' /boot/uEnv.txt -reboot -# Clone and build the code -cd -git clone -b opc-server https://github.com/jadonk/LEDscape.git -cd LEDscape -make -cd -git clone https://github.com/jadonk/openpixelcontrol.git -# Load and configure the kernel module, pins and LEDscape daemon -config-pin overlay BB-OPC-EX -modprobe uio_pruss -./LEDscape/run-ledscape & -# Run an example Python script -./openpixelcontrol/python_clients/example.py diff --git a/books/beaglebone-cookbook/03displays/code/nokia5110.js b/books/beaglebone-cookbook/03displays/code/nokia5110.js deleted file mode 100644 index 9a43c98b..00000000 --- a/books/beaglebone-cookbook/03displays/code/nokia5110.js +++ /dev/null @@ -1,18 +0,0 @@ -#!/usr/bin/env node -// -// Copyright (C) 2012 - Cabin Programs, Ken Keller -// - -var lcd = require('nokia5110'); -var b = require('bonescript'); -var timeout = 0; -var inverseIndex; - -// -// Must define the following outputs -// -lcd.PIN_SDIN = "P9_17"; -lcd.PIN_SCLK = "P9_21"; -lcd.PIN_SCE = "P9_11"; -lcd.PIN_DC = "P9_15"; -lcd.PIN_RESET= "P9_13"; \ No newline at end of file diff --git a/books/beaglebone-cookbook/03displays/code/nokia5110Test.js b/books/beaglebone-cookbook/03displays/code/nokia5110Test.js deleted file mode 100755 index a823f819..00000000 --- a/books/beaglebone-cookbook/03displays/code/nokia5110Test.js +++ /dev/null @@ -1,231 +0,0 @@ -#!/usr/bin/env node -// -// Copyright (C) 2012 - Cabin Programs, Ken Keller -// - -var lcd = require('nokia5110'); -var b = require('bonescript'); -var timeout = 0; -var inverseIndex; - -// -// Must define the following outputs to use LCD_5110.js -// -lcd.PIN_SDIN = "P9_17"; -lcd.PIN_SCLK = "P9_21"; -lcd.PIN_SCE = "P9_11"; -lcd.PIN_DC = "P9_15"; -lcd.PIN_RESET= "P9_13"; - -lcd.setup(); -setTimeout(loop, 0); -// loop(); - -function loop() { -// test bitmap write - console.log("test bitmap write"); -// lcd.clear(); - lcd.gotoXY(0, 0); - lcd.bitmap(beagle); - - inverseIndex = 0; - setTimeout(loop0, 1000*timeout); -} - -function loop0() { -// test inverse video - console.log("test inverse video"); - if(inverseIndex % 2) { - lcd.inverse(lcd.LCD_INVERSE); - } else { - lcd.inverse(lcd.LCD_NORMAL); - } - - inverseIndex++; - - if(inverseIndex < 19) { - setTimeout(loop0, 50*timeout); - } else { - setTimeout(loop1, 50*timeout); - } -} - -function loop1() { -// test normal character write - console.log("test normal character write"); - // lcd.clear(); - lcd.gotoXY(0, 0); - for ( index = 0x41 ; index < 0x7b ; index++) - lcd.character(String.fromCharCode(index)); - - setTimeout(loop2, 2000*timeout); -} - -function loop2() { -// test bitmap and string write - console.log("test bitmap and string write"); - // lcd.clear(); - lcd.gotoXY(0, 0); - lcd.bitmap(world_map); - - setTimeout(loop3, 1000*timeout); -} - -function loop3() { - var index; - - for (index=0; index<5; index++) - { - lcd.gotoXY(0, 3); - lcd.string('HELLO WORLD!'); - lcd.gotoXY(0, 3); - lcd.string('hello world!'); - } - - setTimeout(loop4, 0); -} - -function loop4() { - var index; - -// test solid block character - console.log("test solid block character"); - // lcd.clear(); - lcd.gotoXY(0, 0); - for ( index = 0 ; index < 72 ; index++) - lcd.character(String.fromCharCode(0x7f)); - -// Scrolling text test - console.log("Scrolling text test"); - // lcd.clear(); - var theTEXT = "Scroll text..."; - var numScrolls = lcd.scrollLength(theTEXT) * 2; - - lcd.scrollInit(3); - for (index=0; index<numScrolls; index++) - { - lcd.scroll(3,theTEXT); - } - lcd.scrollInit(3); // used to clear row - - setTimeout(loop5, 2000*timeout); -} - -function loop5() { - var index; - -// Progress Bar test - console.log("Progress Bar test"); - lcd.gotoXY(0,0); - lcd.string("Progress Bar"); - - lcd.progressInit(2); - for (index=0; index<101; index+=2) - lcd.progressBar(2,index); - - for (index=100; index>=0; index-=2) - lcd.progressBar(2,index); - - lcd.progressInit(2); - for (index=100; index>=0; index-=6) - lcd.progressBar(2,index); - - if(timeout) setTimeout(loop, 2000); -} - -var beagle = [ -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xC0, 0x60, 0x60, 0x60, 0x60, 0x60, 0x70, 0xF8, 0xFC, -0x9C, 0x0C, 0x07, 0x07, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x07, 0x06, 0x0C, -0x1C, 0x18, 0x30, 0xE0, 0xC0, 0xC0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xE0, 0x70, 0x1E, 0x07, 0x01, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x03, 0x7F, 0xF8, 0xE0, 0x00, 0x00, 0xE0, 0xB0, 0x90, 0xF0, 0xE0, 0xE0, -0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6D, 0x6D, 0x77, 0xFF, 0xEE, 0xF8, 0xC0, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xE0, 0x38, 0x1E, 0x0F, 0x01, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x3F, 0xFF, 0xF8, 0x81, 0x02, -0x02, 0x03, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x03, 0x03, 0x02, 0x02, 0x06, 0x06, 0x84, 0xCC, 0x9C, 0xF8, 0x70, 0x70, 0x60, 0xC0, 0xC0, -0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xF0, 0xFE, 0xF7, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x07, 0x1F, 0xFC, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x1F, 0x7F, 0x78, 0xF8, 0xFC, 0xFC, -0xFE, 0xFE, 0x7E, 0x7F, 0x7F, 0xE2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x07, 0x3F, 0xFF, 0xC0, -0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xC0, 0xFF, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xC0, 0xC0, 0xE0, 0xE0, 0x60, -0x20, 0x30, 0x30, 0xD0, 0x98, 0x08, 0x1C, 0x3E, 0x63, 0xC1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0xE0, 0x30, 0x31, 0x33, 0xF7, 0xEF, 0x0E, 0x0C, 0x1C, 0x38, 0xF8, 0xF8, 0x18, 0x18, 0x18, -0x18, 0x18, 0x18, 0x18, 0x1C, 0x1C, 0x0E, 0x0E, 0x07, 0x03, 0x01, 0x00, 0x00, 0x00, 0x10, 0x10, -0x30, 0x30, 0x60, 0x60, 0x60, 0x60, 0x40, 0x45, 0x43, 0x43, 0x47, 0x47, 0x7F, 0x7F, 0xFF, 0xFF, -0x0F, 0x0F, 0x0F, 0x0E, 0x1D, 0x38, 0x30, 0x30, 0x21, 0x23, 0x24, 0x24, 0x38, 0x0F, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFA, 0xF0, 0xE0, 0x8F, 0x3F, 0x7E, 0xD8, 0x30, 0xF0, 0xFF, -0xFF, 0x00, 0x00, 0x00, 0xC0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xC0, 0x00, -0x00, 0x02, 0x06, 0xFF, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x0F, 0x3F, 0xFC, 0xF0, -0xE0, 0x01, 0x03, 0x03, 0x01, 0x00, 0x00, 0x00, 0x1F, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, -0xF0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xF0, 0x00, 0x00, 0x00, 0x00, -0x70, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x01, 0x03, 0x87, 0xFE, 0x7C, 0x60, 0x00, 0x00, 0x00, 0xC0, 0xFF, 0x3F, 0x00, -0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0x0F, -0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x3F, 0xFE, 0x00, 0x00, 0x3C, 0x7F, 0xFF, 0xE0, 0xC0, 0x80, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x3F, 0xFF, 0xE1, 0xC0, 0xC0, 0x80, 0xE0, 0x78, 0x0E, -0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xDF, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x70, 0xF1, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x0D, 0x30, 0xE0, 0x80, 0x80, -0x80, 0x81, 0xFF, 0xFF, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, -0x20, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0xC0, 0x20, 0x20, 0x00, -0xF7, 0x5E, 0x5E, 0x0C, 0xEC, 0x8C, 0x84, 0x0E, 0xBE, 0x9E, 0x9F, 0x0F, 0x87, 0x91, 0x80, 0x00, -0x90, 0x90 ]; - -var world_map = [ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x80, 0x00, 0x60, 0xC0, 0xF0, 0xDC, 0x7C, 0X3C, 0x1C, 0xF0, 0xF8, 0xF0, 0xF0, - 0xF8, 0xF8, 0xFE, 0xFE, 0xE6, 0xD4, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, - 0x40, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0xB0, 0x70, - 0xC0, 0x60, 0x00, 0xB0, 0x90, 0x28, 0xE3, 0x41, 0xC0, 0x81, 0x01, 0x03, 0x0F, 0x3F, 0xFF, - 0xFF, 0xFF, 0xFF, 0xBF, 0x0F, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x81, - 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x70, 0x08, 0x84, 0x40, 0x00, 0xE0, 0x80, 0xF0, 0xF8, - 0xF8, 0xFC, 0xFC, 0xEC, 0xE0, 0xE0, 0xE0, 0xE0, 0xC0, 0xC0, 0xE0, 0xC0, 0xC0, 0x80, 0x00, - 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x0B, 0x3F, 0x0F, 0x0F, 0x0F, 0x0F, 0x1F, 0x3F, 0xFF, 0xFF, 0xFF, - 0xFE, 0xFF, 0xFE, 0xFE, 0xE7, 0xC1, 0xC1, 0x00, 0xF8, 0xF7, 0xE5, 0xC0, 0x00, 0x03, 0x0F, - 0x07, 0x01, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x80, 0x00, 0x98, 0xBC, 0xD7, 0xE9, - 0xEF, 0xFF, 0xFD, 0xFC, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFE, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0x0F, 0x0F, 0x0F, 0x0F, 0x3F, - 0x0F, 0x0F, 0x07, 0x03, 0x02, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x1F, - 0x3F, 0x7F, 0xFF, 0x7F, 0x3F, 0x3E, 0x3D, 0x1B, 0x07, 0x03, 0x01, 0x00, 0x01, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xC0, 0xEC, 0xED, 0xF3, 0xF3, 0xE5, 0xC3, 0xEF, - 0xE7, 0xE9, 0x29, 0xFB, 0xFF, 0xB1, 0xBD, 0x7F, 0x7F, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, - 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x67, 0x07, 0x07, 0x13, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x01, 0x00, 0x03, 0x02, 0x30, 0xFC, 0xFC, 0xFC, 0xF8, 0xF8, 0xE0, 0xE0, - 0xE0, 0x40, 0x00, 0x00, 0x00, 0x00, 0x03, 0x07, 0x07, 0x07, 0x07, 0x07, 0xBF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0x1E, 0x0F, 0x05, 0x01, 0x00, 0x00, 0x00, 0x00, 0x07, 0x01, 0x00, 0x00, - 0x01, 0x11, 0x23, 0x10, 0x10, 0x00, 0x00, 0x00, 0x80, 0x20, 0xA0, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x7F, 0x3F, 0x0F, 0x0F, 0x03, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x07, 0x0F, - 0x0F, 0x07, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x06, 0x0E, 0x0F, 0x0F, 0x0F, 0x0F, 0x1F, 0x5E, 0x0C, 0x00, 0x00, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ]; - diff --git a/books/beaglebone-cookbook/03displays/code/pwmTest.sh b/books/beaglebone-cookbook/03displays/code/pwmTest.sh deleted file mode 100755 index 188ef6ff..00000000 --- a/books/beaglebone-cookbook/03displays/code/pwmTest.sh +++ /dev/null @@ -1,22 +0,0 @@ -#!/usr/bin/env bash - -# config-pin P9_14 pwm - -PWMPATH=/sys/class/pwm - -echo Testing pwmchip$1 pwm$2 in -echo $PWMPATH/pwmchip$1 - - -cd $PWMPATH/pwmchip$1 -sudo chgrp gpio * -sudo chmod g+w * -echo $2 > export - -cd pwm$2 -sudo chgrp gpio * -sudo chmod g+w * -ls -ls -echo 1000000000 > period -echo 500000000 > duty_cycle -echo 1 > enable \ No newline at end of file diff --git a/books/beaglebone-cookbook/03displays/code/speak.js b/books/beaglebone-cookbook/03displays/code/speak.js deleted file mode 100755 index 9ee797de..00000000 --- a/books/beaglebone-cookbook/03displays/code/speak.js +++ /dev/null @@ -1,27 +0,0 @@ -#!/usr/bin/env node - -var exec = require('child_process').exec; - -function speakForSelf(phrase) { -{ - exec('flite -t "' + phrase + '"', function (error, stdout, stderr) { - console.log(stdout); - if(error) { - console.log('error: ' + error); - } - if(stderr) { - console.log('stderr: ' + stderr); - } - }); -} - -speakForSelf("Hello, My name is Borris. " + - "I am a BeagleBone Black, " + - "a true open hardware, " + - "community-supported embedded computer for developers and hobbyists. " + - "I am powered by a 1 Giga Hertz Sitara™ ARM® Cortex-A8 processor. " + - "I boot Linux in under 10 seconds. " + - "You can get started on development in " + - "less than 5 minutes with just a single USB cable." + - "Bark, bark!" - ); \ No newline at end of file diff --git a/books/beaglebone-cookbook/03displays/displays.rst b/books/beaglebone-cookbook/03displays/displays.rst index 3abec72f..dcd7c689 100644 --- a/books/beaglebone-cookbook/03displays/displays.rst +++ b/books/beaglebone-cookbook/03displays/displays.rst @@ -57,25 +57,25 @@ a more traditional editor (as shown in :ref:`tips_editing_files`). .. _py_internLED_code: -.. literalinclude:: code/internLED.py +.. literalinclude:: ../code/03displays/internLED.py :caption: Using an internal LED (internLED.py) :linenos: -:download:`internLED.py <code/internLED.py>` +:download:`internLED.py <../code/03displays/internLED.py>` .. _js_internLED_code: -.. literalinclude:: code/internLED.js +.. literalinclude:: ../code/03displays/internLED.js :caption: Using an internal LED (internLED.js) :linenos: -:download:`internLED.js <code/internLED.js>` +:download:`internLED.js <../code/03displays/internLED.js>` In the *bash* command window, enter the following commands: .. code-block:: bash - bone$ cd ~/BoneCookbook/docs/03displays/code + bone$ cd ~/beaglebone-cookbook-code/03displays bone$ ./internLED.js @@ -126,19 +126,19 @@ and find the code shown in :ref:`py_externLED_code`. .. _py_externLED_code: -.. literalinclude:: code/externLED.py +.. literalinclude:: ../code/03displays/externLED.py :caption: Code for using an external LED (externLED.py) :linenos: -:download:`externLED.py <code/externLED.py>` +:download:`externLED.py <../code/03displays/externLED.py>` .. _js_externLED_code: -.. literalinclude:: code/externLED.js +.. literalinclude:: ../code/03displays/externLED.js :caption: Code for using an external LED (externLED.js) :linenos: -:download:`externLED.js <code/externLED.js>` +:download:`externLED.js <../code/03displays/externLED.js>` Save your file and run the code as before (:ref:`displays_onboardLED`). @@ -201,19 +201,19 @@ Then run it as before. .. _py_fadeLED_code: -.. literalinclude:: code/fadeLED.py +.. literalinclude:: ../code/03displays/fadeLED.py :caption: Code for using an external LED (fadeLED.py) :linenos: -:download:`fadeLED.py <code/fadeLED.py>` +:download:`fadeLED.py <../code/03displays/fadeLED.py>` .. _js_fadeLED_code: -.. literalinclude:: code/fadeLED.js +.. literalinclude:: ../code/03displays/fadeLED.js :caption: Code for using an external LED (fadeLED.js) :linenos: -:download:`fadeLED.js <code/fadeLED.js>` +:download:`fadeLED.js <../code/03displays/fadeLED.js>` The Bone has several outputs that can be use as pwm's as shown in :ref:`cape-headers-pwm_fig`. There are three *EHRPWM's* which each has a pair of pwm channels. Each pair must have the same period. @@ -354,7 +354,7 @@ LED matrix display (matrixLEDi2c.py) .. code-block:: C - include::code/matrixLEDi2c.py + include::../code/03displays/matrixLEDi2c.py 1. This line states which bus to use. The last digit gives the BoneScript bus number. @@ -461,7 +461,7 @@ Writing to a NeoPixel LED String Using LEDscape .. // [source, bash] .. // ---- -.. // include::code/neoPixel.sh +.. // include::../code/03displays/neoPixel.sh .. // ---- .. // ==== @@ -490,10 +490,10 @@ Then add the code from :ref:`speak_code` in a file called ``speak.js`` and run. .. _speak_code: -.. literalinclude:: code/speak.js +.. literalinclude:: ../code/03displays/speak.js :caption: A program that talks (speak.js) :linenos: -:download:`speak.js <code/speak.js>` +:download:`speak.js <../code/03displays/speak.js>` See :ref:`sensors_audio` to see how to use a USB audio dongle and set your default audio out. diff --git a/books/beaglebone-cookbook/04motors/code/bipolarStepperMotor.py b/books/beaglebone-cookbook/04motors/code/bipolarStepperMotor.py deleted file mode 100755 index 2b0b2caf..00000000 --- a/books/beaglebone-cookbook/04motors/code/bipolarStepperMotor.py +++ /dev/null @@ -1,91 +0,0 @@ -#!/usr/bin/env python -import time -import os -import signal -import sys - -# Motor is attached here -# controller = ["P9_11", "P9_13", "P9_15", "P9_17"]; -# controller = ["30", "31", "48", "5"] -# controller = ["P9_14", "P9_16", "P9_18", "P9_22"]; -controller = ["50", "51", "4", "2"] -states = [[1,0,0,0], [0,1,0,0], [0,0,1,0], [0,0,0,1]] -statesHiTorque = [[1,1,0,0], [0,1,1,0], [0,0,1,1], [1,0,0,1]] -statesHalfStep = [[1,0,0,0], [1,1,0,0], [0,1,0,0], [0,1,1,0], - [0,0,1,0], [0,0,1,1], [0,0,0,1], [1,0,0,1]] - -curState = 0 # Current state -ms = 100 # Time between steps, in ms -maxStep = 22 # Number of steps to turn before turning around -minStep = 0 # minimum step to turn back around on - -CW = 1 # Clockwise -CCW = -1 -pos = 0 # current position and direction -direction = CW -GPIOPATH="/sys/class/gpio" - -def signal_handler(sig, frame): - print('Got SIGINT, turning motor off') - for i in range(len(controller)) : - f = open(GPIOPATH+"/gpio"+controller[i]+"/value", "w") - f.write('0') - f.close() - sys.exit(0) -signal.signal(signal.SIGINT, signal_handler) -print('Hit ^C to stop') - -def move(): - global pos - global direction - global minStep - global maxStep - pos += direction - print("pos: " + str(pos)) - # Switch directions if at end. - if (pos >= maxStep or pos <= minStep) : - direction *= -1 - rotate(direction) - -# This is the general rotate -def rotate(direction) : - global curState - global states - # print("rotate(%d)", direction); - # Rotate the state acording to the direction of rotation - curState += direction - if(curState >= len(states)) : - curState = 0; - elif(curState<0) : - curState = len(states)-1 - updateState(states[curState]) - -# Write the current input state to the controller -def updateState(state) : - global controller - print(state) - for i in range(len(controller)) : - f = open(GPIOPATH+"/gpio"+controller[i]+"/value", "w") - f.write(str(state[i])) - f.close() - -# Initialize motor control pins to be OUTPUTs -for i in range(len(controller)) : - # Make sure pin is exported - if (not os.path.exists(GPIOPATH+"/gpio"+controller[i])): - f = open(GPIOPATH+"/export", "w") - f.write(pin) - f.close() - # Make it an output pin - f = open(GPIOPATH+"/gpio"+controller[i]+"/direction", "w") - f.write("out") - f.close() - -# Put the motor into a known state -updateState(states[0]) -rotate(direction) - -# Rotate -while True: - move() - time.sleep(ms/1000) diff --git a/books/beaglebone-cookbook/04motors/code/dcMotor.js b/books/beaglebone-cookbook/04motors/code/dcMotor.js deleted file mode 100755 index 09c798c9..00000000 --- a/books/beaglebone-cookbook/04motors/code/dcMotor.js +++ /dev/null @@ -1,44 +0,0 @@ -#!/usr/bin/env node -//////////////////////////////////////// -// dcMotor.js -// This is an example of driving a DC motor -// Wiring: -// Setup: config-pin P9_16 pwm -// See: -//////////////////////////////////////// -const fs = require("fs"); - -const pwmPeriod = '1000000'; // Period in ns -const pwm = '1'; // pwm to use -const channel = 'b'; // channel to use -const PWMPATH='/dev/bone/pwm/'+pwm+'/'+channel; - -const low = 0.05, // Slowest speed (duty cycle) - hi = 1, // Fastest (always on) - ms = 100; // How often to change speed, in ms -var speed = 0.5, // Current speed; - step = 0.05; // Change in speed - -// fs.writeFileSync(PWMPATH+'/export', pwm); // Export the pwm channel -// Set the period in ns, first 0 duty_cycle, -fs.writeFileSync(PWMPATH+'/duty_cycle', '0'); -fs.writeFileSync(PWMPATH+'/period', pwmPeriod); -fs.writeFileSync(PWMPATH+'/duty_cycle', pwmPeriod/2); -fs.writeFileSync(PWMPATH+'/enable', '1'); - -timer = setInterval(sweep, ms); - -function sweep() { - speed += step; - if(speed > hi || speed < low) { - step *= -1; - } - fs.writeFileSync(PWMPATH+'/duty_cycle', parseInt(pwmPeriod*speed)); - // console.log('speed = ' + speed); -} - -process.on('SIGINT', function() { - console.log('Got SIGINT, turning motor off'); - clearInterval(timer); // Stop the timer - fs.writeFileSync(PWMPATH+'/enable', '0'); -}); \ No newline at end of file diff --git a/books/beaglebone-cookbook/04motors/code/dcMotor.py b/books/beaglebone-cookbook/04motors/code/dcMotor.py deleted file mode 100755 index 755eaf84..00000000 --- a/books/beaglebone-cookbook/04motors/code/dcMotor.py +++ /dev/null @@ -1,50 +0,0 @@ -#!/usr/bin/env python -# //////////////////////////////////////// -# // dcMotor.js -# // This is an example of driving a DC motor -# // Wiring: -# // Setup: config-pin P9_16 pwm -# // See: -# //////////////////////////////////////// -import time -import signal -import sys - -def signal_handler(sig, frame): - print('Got SIGINT, turning motor off') - f = open(PWMPATH+'/enable', 'w') - f.write('0') - f.close() - sys.exit(0) -signal.signal(signal.SIGINT, signal_handler) - -pwmPeriod = '1000000' # Period in ns -pwm = '1' # pwm to use -channel = 'b' # channel to use -PWMPATH='/dev/bone/pwm/'+pwm+'/'+channel - -low = 0.05 # Slowest speed (duty cycle) -hi = 1 # Fastest (always on) -ms = 100 # How often to change speed, in ms -speed = 0.5 # Current speed -step = 0.05 # Change in speed - -f = open(PWMPATH+'/duty_cycle', 'w') -f.write('0') -f.close() -f = open(PWMPATH+'/period', 'w') -f.write(pwmPeriod) -f.close() -f = open(PWMPATH+'/enable', 'w') -f.write('1') -f.close() - -f = open(PWMPATH+'/duty_cycle', 'w') -while True: - speed += step - if(speed > hi or speed < low): - step *= -1 - duty_cycle = str(round(speed*1000000)) # Convert ms to ns - f.seek(0) - f.write(duty_cycle) - time.sleep(ms/1000) diff --git a/books/beaglebone-cookbook/04motors/code/h-bridgeMotor.js b/books/beaglebone-cookbook/04motors/code/h-bridgeMotor.js deleted file mode 100755 index 239418dd..00000000 --- a/books/beaglebone-cookbook/04motors/code/h-bridgeMotor.js +++ /dev/null @@ -1,54 +0,0 @@ -#!/usr/bin/env node - -// This example uses an H-bridge to drive a DC motor in two directions - -var b = require('bonescript'); - -var enable = 'P9_21'; // Pin to use for PWM speed control - in1 = 'P9_15', - in2 = 'P9_16', - step = 0.05, // Change in speed - min = 0.05, // Min duty cycle - max = 1.0, // Max duty cycle - ms = 100, // Update time, in ms - speed = min; // Current speed; - -b.pinMode(enable, b.ANALOG_OUTPUT, 6, 0, 0, doInterval); -b.pinMode(in1, b.OUTPUT); -b.pinMode(in2, b.OUTPUT); - -function doInterval(x) { - if(x.err) { - console.log('x.err = ' + x.err); - return; - } - timer = setInterval(sweep, ms); -} - -clockwise(); // Start by going clockwise - -function sweep() { - speed += step; - if(speed > max || speed < min) { - step *= -1; - step>0 ? clockwise() : counterClockwise(); - } - b.analogWrite(enable, speed); - console.log('speed = ' + speed); -} - -function clockwise() { - b.digitalWrite(in1, b.HIGH); - b.digitalWrite(in2, b.LOW); -} - -function counterClockwise() { - b.digitalWrite(in1, b.LOW); - b.digitalWrite(in2, b.HIGH); -} - -process.on('SIGINT', function() { - console.log('Got SIGINT, turning motor off'); - clearInterval(timer); // Stop the timer - b.analogWrite(enable, 0); // Turn motor off -}); \ No newline at end of file diff --git a/books/beaglebone-cookbook/04motors/code/ring.js b/books/beaglebone-cookbook/04motors/code/ring.js deleted file mode 100755 index a383eae4..00000000 --- a/books/beaglebone-cookbook/04motors/code/ring.js +++ /dev/null @@ -1,40 +0,0 @@ -#!/usr/bin/env node - -// Drive a simple servo motor back and forth - -var b = require('bonescript'); - -var motor = 'P9_21', // Pin to control servo - freq = 50, // Servo frequency (20 ms) - min = 0.8, // Smallest angle (in ms) - max = 2.5, // Largest angle (in ms) - ms = 500, // How often to change position, in ms - pos = 1.5, // Current position, about middle - step = 0.1; // Step size to next position -var timer; - -console.log('Hit ^C to stop'); -b.pinMode(motor, b.ANALOG_OUTPUT); - -pos1(); - -function pos1() { - move(0.9); - timer = setTimeout(pos2, ms); -} -function pos2() { - move(2.1); // Start in the middle - timer = setTimeout(pos1, ms); -} - -function move(pos) { - var dutyCycle = pos/1000*freq; - b.analogWrite(motor, dutyCycle, freq); - console.log('pos = ' + pos.toFixed(3) + ' duty cycle = ' + dutyCycle.toFixed(3)); -} - -process.on('SIGINT', function() { - console.log('Got SIGINT, turning motor off'); - clearTimeout(timer); // Stop the timer - b.analogWrite(motor, 0, 0); // Turn motor off -}); \ No newline at end of file diff --git a/books/beaglebone-cookbook/04motors/code/servoBird.js b/books/beaglebone-cookbook/04motors/code/servoBird.js deleted file mode 100755 index 29466b94..00000000 --- a/books/beaglebone-cookbook/04motors/code/servoBird.js +++ /dev/null @@ -1,22 +0,0 @@ -#!/usr/bin/env node -var b = require('bonescript'); -var motor = 'P9_14'; // Pin to use -var freq = 80; // Servo frequency -var dir = 0.001, // Direction - min = 0.05, - max = 0.15, - ms = 50, - pos = min; // Current position; - -b.pinMode(motor, b.ANALOG_OUTPUT); - -setInterval(move, ms); - -function move() { - pos += dir; - if(pos > max || pos < min) { - dir = -1 * dir; - } - b.analogWrite(motor, pos, freq); - console.log('pos = ' + pos); -} diff --git a/books/beaglebone-cookbook/04motors/code/servoEncoder.py b/books/beaglebone-cookbook/04motors/code/servoEncoder.py deleted file mode 100755 index 70724954..00000000 --- a/books/beaglebone-cookbook/04motors/code/servoEncoder.py +++ /dev/null @@ -1,98 +0,0 @@ -#!/usr/bin/env python -# //////////////////////////////////////// -# // servoEncoder.py -# // Drive a simple servo motor using rotary encoder viq eQEP -# // Wiring: Servo on P9_16, rotary encoder on P8_11 and P8_12 -# // Setup: config-pin P9_16 pwm -# // config-pin P8_11 eqep -# // config-pin P8_12 eqep -# // See: -# //////////////////////////////////////// -import time -import signal -import sys - -# Set up encoder -eQEP = '2' -COUNTERPATH = '/dev/bone/counter/counter'+eQEP+'/count0' -maxCount = '180' - -ms = 100 # Time between samples in ms - -# Set the eEQP maximum count -fQEP = open(COUNTERPATH+'/ceiling', 'w') -fQEP.write(maxCount) -fQEP.close() - -# Enable -fQEP = open(COUNTERPATH+'/enable', 'w') -fQEP.write('1') -fQEP.close() - -fQEP = open(COUNTERPATH+'/count', 'r') - -# Set up servo -pwmPeriod = '20000000' # Period in ns, (20 ms) -pwm = '1' # pwm to use -channel = 'b' # channel to use -PWMPATH='/dev/bone/pwm/'+pwm+'/'+channel -low = 0.6 # Smallest angle (in ms) -hi = 2.5 # Largest angle (in ms) -ms = 250 # How often to change position, in ms -pos = 1.5 # Current position, about middle ms) -step = 0.1 # Step size to next position - -def signal_handler(sig, frame): - print('Got SIGINT, turning motor off') - f = open(PWMPATH+'/enable', 'w') - f.write('0') - f.close() - sys.exit(0) -signal.signal(signal.SIGINT, signal_handler) - -f = open(PWMPATH+'/period', 'w') -f.write(pwmPeriod) -f.close() -f = open(PWMPATH+'/duty_cycle', 'w') -f.write(str(round(int(pwmPeriod)/2))) -f.close() -f = open(PWMPATH+'/enable', 'w') -f.write('1') -f.close() - -print('Hit ^C to stop') - -olddata = -1 -while True: - fQEP.seek(0) - data = fQEP.read()[:-1] - # Print only if data changes - if data != olddata: - olddata = data - # print("data = " + data) - # # map 0-180 to low-hi - duty_cycle = -1*int(data)*(hi-low)/180.0 + hi - duty_cycle = str(int(duty_cycle*1000000)) # Convert from ms to ns - # print('duty_cycle = ' + duty_cycle) - f = open(PWMPATH+'/duty_cycle', 'w') - f.write(duty_cycle) - f.close() - time.sleep(ms/1000) - -# Black OR Pocket -# eQEP0: P9.27 and P9.42 OR P1_33 and P2_34 -# eQEP1: P9.33 and P9.35 -# eQEP2: P8.11 and P8.12 OR P2_24 and P2_33 - -# AI -# eQEP1: P8.33 and P8.35 -# eQEP2: P8.11 and P8.12 or P9.19 and P9.41 -# eQEP3: P8.24 abd P8.25 or P9.27 and P9.42 - -# | Pin | pwm | channel -# | P9_31 | 0 | a -# | P9_29 | 0 | b -# | P9_14 | 1 | a -# | P9_16 | 1 | b -# | P8_19 | 2 | a -# | P8_13 | 2 | b diff --git a/books/beaglebone-cookbook/04motors/code/servoMotor.js b/books/beaglebone-cookbook/04motors/code/servoMotor.js deleted file mode 100755 index efe02880..00000000 --- a/books/beaglebone-cookbook/04motors/code/servoMotor.js +++ /dev/null @@ -1,50 +0,0 @@ -#!/usr/bin/env node -//////////////////////////////////////// -// servoMotor.js -// Drive a simple servo motor back and forth on P9_16 pin -// Wiring: -// Setup: config-pin P9_16 pwm -// See: -//////////////////////////////////////// -const fs = require("fs"); - -const pwmPeriod = '20000000'; // Period in ns, (20 ms) -const pwm = '1'; // pwm to use -const channel = 'b'; // channel to use -const PWMPATH='/dev/bone/pwm/'+pwm+'/'+channel; -const low = 0.8, // Smallest angle (in ms) - hi = 2.4, // Largest angle (in ms) - ms = 250; // How often to change position, in ms -var pos = 1.5, // Current position, about middle ms) - step = 0.1; // Step size to next position - -console.log('Hit ^C to stop'); -fs.writeFileSync(PWMPATH+'/period', pwmPeriod); -fs.writeFileSync(PWMPATH+'/enable', '1'); - -var timer = setInterval(sweep, ms); - -// Sweep from low to hi position and back again -function sweep() { - pos += step; // Take a step - if(pos > hi || pos < low) { - step *= -1; - } - var dutyCycle = parseInt(pos*1000000); // Convert ms to ns - // console.log('pos = ' + pos + ' duty cycle = ' + dutyCycle); - fs.writeFileSync(PWMPATH+'/duty_cycle', dutyCycle); -} - -process.on('SIGINT', function() { - console.log('Got SIGINT, turning motor off'); - clearInterval(timer); // Stop the timer - fs.writeFileSync(PWMPATH+'/enable', '0'); -}); - -// | Pin | pwm | channel -// | P9_31 | 0 | a -// | P9_29 | 0 | b -// | P9_14 | 1 | a -// | P9_16 | 1 | b -// | P8_19 | 2 | a -// | P8_13 | 2 | b \ No newline at end of file diff --git a/books/beaglebone-cookbook/04motors/code/servoMotor.py b/books/beaglebone-cookbook/04motors/code/servoMotor.py deleted file mode 100755 index 324bc7be..00000000 --- a/books/beaglebone-cookbook/04motors/code/servoMotor.py +++ /dev/null @@ -1,56 +0,0 @@ -#!/usr/bin/env python -# //////////////////////////////////////// -# // servoMotor.py -# // Drive a simple servo motor back and forth on P9_16 pin -# // Wiring: -# // Setup: config-pin P9_16 pwm -# // See: -# //////////////////////////////////////// -import time -import signal -import sys - -pwmPeriod = '20000000' # Period in ns, (20 ms) -pwm = '1' # pwm to use -channel = 'b' # channel to use -PWMPATH='/dev/bone/pwm/'+pwm+'/'+channel -low = 0.8 # Smallest angle (in ms) -hi = 2.4 # Largest angle (in ms) -ms = 250 # How often to change position, in ms -pos = 1.5 # Current position, about middle ms) -step = 0.1 # Step size to next position - -def signal_handler(sig, frame): - print('Got SIGINT, turning motor off') - f = open(PWMPATH+'/enable', 'w') - f.write('0') - f.close() - sys.exit(0) -signal.signal(signal.SIGINT, signal_handler) -print('Hit ^C to stop') - -f = open(PWMPATH+'/period', 'w') -f.write(pwmPeriod) -f.close() -f = open(PWMPATH+'/enable', 'w') -f.write('1') -f.close() - -f = open(PWMPATH+'/duty_cycle', 'w') -while True: - pos += step # Take a step - if(pos > hi or pos < low): - step *= -1 - duty_cycle = str(round(pos*1000000)) # Convert ms to ns - # print('pos = ' + str(pos) + ' duty_cycle = ' + duty_cycle) - f.seek(0) - f.write(duty_cycle) - time.sleep(ms/1000) - -# | Pin | pwm | channel -# | P9_31 | 0 | a -# | P9_29 | 0 | b -# | P9_14 | 1 | a -# | P9_16 | 1 | b -# | P8_19 | 2 | a -# | P8_13 | 2 | b \ No newline at end of file diff --git a/books/beaglebone-cookbook/04motors/code/servoSense.js b/books/beaglebone-cookbook/04motors/code/servoSense.js deleted file mode 100755 index 3dfe2f1f..00000000 --- a/books/beaglebone-cookbook/04motors/code/servoSense.js +++ /dev/null @@ -1,46 +0,0 @@ -#!/usr/bin/env node - -// Bird will bow when there is a change in the sersor distance. - -var b = require('bonescript'); -var motor = 'P9_14'; // Pin to use -var freq = 50; // Servo frequency (20 ms) -var up = 0.6, // Smallest angle (in ms) - down = 2.0, // Largest angle (in ms) - dutyCycle, - ms = 250, // How often to change position, in ms - oldPos = 0; - -b.pinMode(motor, b.ANALOG_OUTPUT, 6, 0, 0, doInterval); - -function doInterval(x) { - if(x.err) { - console.log('x.err = ' + x.err); - return; - } - setInterval(readRange, ms); -} - -move(2.0); - -function readRange() { - b.analogRead('P9_37', printStatus); -} -function printStatus(x) { - var pos = x.value; - console.log('pos = ' + pos); - if (pos-oldPos>0.5) { - move(up); - } - if (oldPos-pos>0.5) { - move(down); - } - oldPos = pos; -} - -function move(pos) { - - dutyCycle = pos/1000*freq - b.analogWrite(motor, dutyCycle, freq); - console.log('pos = ' + pos + ' duty cycle = ' + dutyCycle); -} diff --git a/books/beaglebone-cookbook/04motors/code/stop.js b/books/beaglebone-cookbook/04motors/code/stop.js deleted file mode 100755 index ff06655a..00000000 --- a/books/beaglebone-cookbook/04motors/code/stop.js +++ /dev/null @@ -1,10 +0,0 @@ -#!/usr/bin/env node -// Used for turning everything off. -var b = require('bonescript'); -var gpio = ['P9_11', 'P9_13', 'P9_14', 'P9_15', 'P9_16']; -var i; - -for(i=0; i<gpio.length; i++) { - b.pinMode(gpio[i], b.OUTPUT); - b.digitalWrite(gpio[i], b.LOW); -} diff --git a/books/beaglebone-cookbook/04motors/code/unipolarStepperMotor.js b/books/beaglebone-cookbook/04motors/code/unipolarStepperMotor.js deleted file mode 100755 index 26032442..00000000 --- a/books/beaglebone-cookbook/04motors/code/unipolarStepperMotor.js +++ /dev/null @@ -1,72 +0,0 @@ -#!/usr/bin/env node -var fs = require('fs'); - -// Motor is attached here -// var controller = ["P9_11", "P9_13", "P9_15", "P9_17"]; -// var controller = ["P9_14", "P9_16", "P9_18", "P9_22"]; -var controller = ["50", "51", "4", "2"]; -var states = [[1,1,0,0], [0,1,1,0], [0,0,1,1], [1,0,0,1]]; - -var curState = 0; // Current state -var ms = 100, // Time between steps, in ms - max = 22, // Number of steps to turn before turning around - min = 0; // Minimum step to turn back around on - -var CW = 1, // Clockwise - CCW = -1, - pos = 0, // current position and direction - direction = CW; -const GPIOPATH="/sys/class/gpio"; - -// Initialize motor control pins to be OUTPUTs -var i; -for(i=0; i<controller.length; i++) { - // Make sure pins are exported - if(!fs.existsSync(GPIOPATH+"/gpio"+controller[i])) { - fs.writeFileSync(GPIOPATH+"/export", controller[i]); - // Make it an output pin - fs.writeFileSync(GPIOPATH+"/gpio"+controller[i]+"/direction", "in"); - } -} - -// Put the motor into a known state -updateState(states[0]); -rotate(direction); - -var timer = setInterval(move, ms); - -// Rotate back and forth once -function move() { - pos += direction; - console.log("pos: " + pos); - // Switch directions if at end. - if (pos >= max || pos <= min) { - direction *= -1; - } - rotate(direction); -} - -// This is the general rotate -function rotate(direction) { - // console.log("rotate(%d)", direction); - // Rotate the state acording to the direction of rotation - curState += direction; - if(curState >= states.length) { - curState = 0; - } else if(curState<0) { - curState = states.length-1; - } - updateState(states[curState]); -} - -// Write the current input state to the controller -function updateState(state) { - console.log("state: " + state); - for (i=0; i<controller.length; i++) { - fs.writeFileSync(GPIOPATH+"/gpio"+controller[i]+"/value", state[i]) - } -} - -process.on('exit', function() { - updateState([0,0,0,0]); // Turn motor off -}); \ No newline at end of file diff --git a/books/beaglebone-cookbook/04motors/code/unipolarStepperMotor.js.diff b/books/beaglebone-cookbook/04motors/code/unipolarStepperMotor.js.diff deleted file mode 100644 index 4a34a776..00000000 --- a/books/beaglebone-cookbook/04motors/code/unipolarStepperMotor.js.diff +++ /dev/null @@ -1,6 +0,0 @@ -# var controller = ["P9_11", "P9_13", "P9_15", "P9_17"]; -controller = ["30", "31", "48", "5"] -var states = [[1,1,0,0], [0,1,1,0], [0,0,1,1], [1,0,0,1]]; -var curState = 0; // Current state -var ms = 100, // Time between steps, in ms - max = 200, // Number of steps to turn before turning around \ No newline at end of file diff --git a/books/beaglebone-cookbook/04motors/code/unipolarStepperMotor.py b/books/beaglebone-cookbook/04motors/code/unipolarStepperMotor.py deleted file mode 100755 index 1d13e416..00000000 --- a/books/beaglebone-cookbook/04motors/code/unipolarStepperMotor.py +++ /dev/null @@ -1,91 +0,0 @@ -#!/usr/bin/env python -import time -import os -import signal -import sys - -# Motor is attached here -# controller = ["P9_11", "P9_13", "P9_15", "P9_17"]; -# controller = ["30", "31", "48", "5"] -# controller = ["P9_14", "P9_16", "P9_18", "P9_22"]; -controller = ["50", "51", "4", "2"] -states = [[1,1,0,0], [0,1,1,0], [0,0,1,1], [1,0,0,1]] -statesHiTorque = [[1,1,0,0], [0,1,1,0], [0,0,1,1], [1,0,0,1]] -statesHalfStep = [[1,0,0,0], [1,1,0,0], [0,1,0,0], [0,1,1,0], - [0,0,1,0], [0,0,1,1], [0,0,0,1], [1,0,0,1]] - -curState = 0 # Current state -ms = 250 # Time between steps, in ms -maxStep = 22 # Number of steps to turn before turning around -minStep = 0 # minimum step to turn back around on - -CW = 1 # Clockwise -CCW = -1 -pos = 0 # current position and direction -direction = CW -GPIOPATH="/sys/class/gpio" - -def signal_handler(sig, frame): - print('Got SIGINT, turning motor off') - for i in range(len(controller)) : - f = open(GPIOPATH+"/gpio"+controller[i]+"/value", "w") - f.write('0') - f.close() - sys.exit(0) -signal.signal(signal.SIGINT, signal_handler) -print('Hit ^C to stop') - -def move(): - global pos - global direction - global minStep - global maxStep - pos += direction - print("pos: " + str(pos)) - # Switch directions if at end. - if (pos >= maxStep or pos <= minStep) : - direction *= -1 - rotate(direction) - -# This is the general rotate -def rotate(direction) : - global curState - global states - # print("rotate(%d)", direction); - # Rotate the state acording to the direction of rotation - curState += direction - if(curState >= len(states)) : - curState = 0; - elif(curState<0) : - curState = len(states)-1 - updateState(states[curState]) - -# Write the current input state to the controller -def updateState(state) : - global controller - print(state) - for i in range(len(controller)) : - f = open(GPIOPATH+"/gpio"+controller[i]+"/value", "w") - f.write(str(state[i])) - f.close() - -# Initialize motor control pins to be OUTPUTs -for i in range(len(controller)) : - # Make sure pin is exported - if (not os.path.exists(GPIOPATH+"/gpio"+controller[i])): - f = open(GPIOPATH+"/export", "w") - f.write(pin) - f.close() - # Make it an output pin - f = open(GPIOPATH+"/gpio"+controller[i]+"/direction", "w") - f.write("out") - f.close() - -# Put the motor into a known state -updateState(states[0]) -rotate(direction) - -# Rotate -while True: - move() - time.sleep(ms/1000) diff --git a/books/beaglebone-cookbook/04motors/code/unipolarStepperMotor.py.diff b/books/beaglebone-cookbook/04motors/code/unipolarStepperMotor.py.diff deleted file mode 100644 index af91b7cd..00000000 --- a/books/beaglebone-cookbook/04motors/code/unipolarStepperMotor.py.diff +++ /dev/null @@ -1,6 +0,0 @@ -# controller = ["P9_11", "P9_13", "P9_15", "P9_17"] -controller = ["30", "31", "48", "5"] -states = [[1,1,0,0], [0,1,1,0], [0,0,1,1], [1,0,0,1]] -curState = 0 // Current state -ms = 100 // Time between steps, in ms -max = 200 // Number of steps to turn before turning around \ No newline at end of file diff --git a/books/beaglebone-cookbook/04motors/motors.rst b/books/beaglebone-cookbook/04motors/motors.rst index 481a684f..d12bd59d 100644 --- a/books/beaglebone-cookbook/04motors/motors.rst +++ b/books/beaglebone-cookbook/04motors/motors.rst @@ -79,25 +79,25 @@ in :ref:`py_servoMotor_code`. You need to configure the pin for PWM. .. code-block:: bash - bone$ <strong>cd ~/BoneCookbook/docs/04motors/code</strong> + bone$ <strong>cd ~/beaglebone-cookbook-code/04motors</strong> bone$ <strong>config-pin P9_16 pwm</strong> bone$ <strong>./servoMotor.py</strong> .. _py_servoMotor_code: -.. literalinclude:: code/servoMotor.py +.. literalinclude:: ../code/04motors/servoMotor.py :caption: Code for driving a servo motor (servoMotor.py) :linenos: -:download:`servoMotor.py <code/servoMotor.py>` +:download:`servoMotor.py <../code/04motors/servoMotor.py>` .. _motors_servoMotor_code: -.. literalinclude:: code/servoMotor.js +.. literalinclude:: ../code/04motors/servoMotor.js :caption: Code for driving a servo motor (servoMotor.js) :linenos: -:download:`servoMotor.js <code/servoMotor.js>` +:download:`servoMotor.js <../code/04motors/servoMotor.js>` Running the code causes the motor to move back and forth, progressing to successive @@ -126,11 +126,11 @@ Combine the code from :ref:`digital_rotaryEncoder_js` and :ref:`motors_servo`. .. _py_servoEncoder_code: -.. literalinclude:: code/servoEncoder.py +.. literalinclude:: ../code/04motors/servoEncoder.py :caption: Code for driving a servo motor with a rotary encorder(servoEncoder.py) :linenos: -:download:`servoEncoder.py <code/servoEncoder.py>` +:download:`servoEncoder.py <../code/04motors/servoEncoder.py>` .. _motors_dcSpeed: @@ -180,19 +180,19 @@ Use the code in :ref:`motors_dcMotor_code` (``dcMotor.js``) to run the motor. .. _py_dcMotor_code: -.. literalinclude:: code/dcMotor.py +.. literalinclude:: ../code/04motors/dcMotor.py :caption: Driving a DC motor in one direction (dcMotor.py) :linenos: -:download:`dcMotor.py <code/dcMotor.py>` +:download:`dcMotor.py <../code/04motors/dcMotor.py>` .. _motors_dcMotor_code: -.. literalinclude:: code/dcMotor.js +.. literalinclude:: ../code/04motors/dcMotor.js :caption: Driving a DC motor in one direction (dcMotor.js) :linenos: -:download:`dcMotor.js <code/dcMotor.js>` +:download:`dcMotor.js <../code/04motors/dcMotor.js>` See Also ========= @@ -238,11 +238,11 @@ motor with a transistor (:ref:`motors_dcMotor_code`). The additional code specif .. _motors_h-bridge_code: -.. literalinclude:: code/h-bridgeMotor.js +.. literalinclude:: ../code/04motors/h-bridgeMotor.js :caption: Code for driving a DC motor with an H-bridge (h-bridgeMotor.js) :linenos: -:download:`h-bridgeMotor.js <code/h-bridgeMotor.js>` +:download:`h-bridgeMotor.js <../code/04motors/h-bridgeMotor.js>` Driving a Bipolar Stepper Motor =============================== @@ -278,11 +278,11 @@ Use the code in :ref:`motors_stepperMotor_code_py` to drive the motor. .. _motors_stepperMotor_code_py: -.. literalinclude:: code/bipolarStepperMotor.py +.. literalinclude:: ../code/04motors/bipolarStepperMotor.py :caption: Driving a bipolar stepper motor (bipolarStepperMotor.py) :linenos: -:download:`bipolarStepperMotor.py <code/bipolarStepperMotor.py>` +:download:`bipolarStepperMotor.py <../code/04motors/bipolarStepperMotor.py>` When you run the code, the stepper motor will rotate back and forth. @@ -335,19 +335,19 @@ so :ref:`motors_unistepperMotor_code` shows only the lines that you need to chan .. _motors_unistepperMotor_js_code: -.. literalinclude:: code/unipolarStepperMotor.py.diff +.. literalinclude:: ../code/04motors/unipolarStepperMotor.py.diff :caption: Changes to bipolar code to drive a unipolar stepper motor (unipolarStepperMotor.py.diff) :linenos: -:download:`unipolarStepperMotor.py.diff <code/unipolarStepperMotor.py.diff>` +:download:`unipolarStepperMotor.py.diff <../code/04motors/unipolarStepperMotor.py.diff>` .. _motors_unistepperMotor_code: -.. literalinclude:: code/unipolarStepperMotor.js.diff +.. literalinclude:: ../code/04motors/unipolarStepperMotor.js.diff :caption: Changes to bipolar code to drive a unipolar stepper motor (unipolarStepperMotor.js.diff) :linenos: -:download:`unipolarStepperMotor.js.diff <code/unipolarStepperMotor.js.diff>` +:download:`unipolarStepperMotor.js.diff <../code/04motors/unipolarStepperMotor.js.diff>` The code in this example makes the following changes: diff --git a/books/beaglebone-cookbook/05tips/code/blinkLED.c b/books/beaglebone-cookbook/05tips/code/blinkLED.c deleted file mode 100755 index 1863c1ef..00000000 --- a/books/beaglebone-cookbook/05tips/code/blinkLED.c +++ /dev/null @@ -1,48 +0,0 @@ -//////////////////////////////////////// -// blinkLED.c -// Blinks the P9_14 pin -// Wiring: -// Setup: -// See: -//////////////////////////////////////// -#include <stdio.h> -#include <string.h> -#include <unistd.h> -#define MAXSTR 100 -// Look up P9.14 using gpioinfo | grep -e chip -e P9.14. chip 1, line 18 maps to 50 -int main() { - FILE *fp; - char pin[] = "50"; - char GPIOPATH[] = "/sys/class/gpio"; - char path[MAXSTR] = ""; - - // Make sure pin is exported - snprintf(path, MAXSTR, "%s%s%s", GPIOPATH, "/gpio", pin); - if (!access(path, F_OK) == 0) { - snprintf(path, MAXSTR, "%s%s", GPIOPATH, "/export"); - fp = fopen(path, "w"); - fprintf(fp, "%s", pin); - fclose(fp); - } - - // Make it an output pin - snprintf(path, MAXSTR, "%s%s%s%s", GPIOPATH, "/gpio", pin, "/direction"); - fp = fopen(path, "w"); - fprintf(fp, "out"); - fclose(fp); - - // Blink every .25 sec - int state = 0; - snprintf(path, MAXSTR, "%s%s%s%s", GPIOPATH, "/gpio", pin, "/value"); - fp = fopen(path, "w"); - while (1) { - fseek(fp, 0, SEEK_SET); - if (state) { - fprintf(fp, "1"); - } else { - fprintf(fp, "0"); - } - state = ~state; - usleep(250000); // sleep time in microseconds - } -} \ No newline at end of file diff --git a/books/beaglebone-cookbook/05tips/code/blinkLED.py b/books/beaglebone-cookbook/05tips/code/blinkLED.py deleted file mode 100755 index 2b15ebd3..00000000 --- a/books/beaglebone-cookbook/05tips/code/blinkLED.py +++ /dev/null @@ -1,13 +0,0 @@ -#!/usr/bin/env python -import Adafruit_BBIO.GPIO as GPIO -import time - -pin = "P9_14" - -GPIO.setup(pin, GPIO.OUT) - -while True: - GPIO.output(pin, GPIO.HIGH) - time.sleep(0.5) - GPIO.output(pin, GPIO.LOW) - time.sleep(0.5) diff --git a/books/beaglebone-cookbook/05tips/code/ipMasquerade.sh b/books/beaglebone-cookbook/05tips/code/ipMasquerade.sh deleted file mode 100755 index 524fb338..00000000 --- a/books/beaglebone-cookbook/05tips/code/ipMasquerade.sh +++ /dev/null @@ -1,31 +0,0 @@ -#!/bin/bash -# These are the commands to run on the host to set up IP -# masquerading so the Bone can access the Internet through -# the USB connection. -# This configures the host, run ./setDNS.sh to configure the Bone. -# Inspired by http://thoughtshubham.blogspot.com/2010/03/ -# internet-over-usb-otg-on-beagleboard.html - -if [ $# -eq 0 ] ; then -echo "Usage: $0 interface (such as eth0 or wlan0)" -exit 1 -fi - -interface=$1 -hostAddr=192.168.7.1 -beagleAddr=192.168.7.2 -ip_forward=/proc/sys/net/ipv4/ip_forward - -if [ `cat $ip_forward` == 0 ] - then - echo "You need to set IP forwarding. Edit /etc/sysctl.conf using:" - echo "$ sudo nano /etc/sysctl.conf" - echo "and uncomment the line \"net.ipv4.ip_forward=1\"" - echo "to enable forwarding of packets. Then run the following:" - echo "$ sudo sysctl -p" - exit 1 - else - echo "IP forwarding is set on host." -fi -# Set up IP masquerading on the host so the bone can reach the outside world -sudo iptables -t nat -A POSTROUTING -s $beagleAddr -o $interface -j MASQUERADE diff --git a/books/beaglebone-cookbook/05tips/code/setDNS.sh b/books/beaglebone-cookbook/05tips/code/setDNS.sh deleted file mode 100755 index a73f1b51..00000000 --- a/books/beaglebone-cookbook/05tips/code/setDNS.sh +++ /dev/null @@ -1,40 +0,0 @@ -#!/bin/bash -# These are the commands to run on the host so the Bone -# can access the Internet through the USB connection. -# Run ./ipMasquerade.sh the first time. It will set up the host. -# Run this script if the host is already set up. -# Inspired by http://thoughtshubham.blogspot.com/2010/03/internet-over-usb-otg-on-beagleboard.html - -hostAddr=192.168.7.1 -beagleAddr=${1:-192.168.7.2} - -# Save the /etc/resolv.conf on the Beagle in case we mess things up. -ssh root@$beagleAddr "mv -n /etc/resolv.conf /etc/resolv.conf.orig" -# Create our own resolv.conf -cat - << EOF > /tmp/resolv.conf -# This is installed by ./setDNS.sh on the host - -EOF - -TMP=/tmp/nmcli -# Look up the nameserver of the host and add it to our resolv.conf -# From: http://askubuntu.com/questions/197036/how-to-know-what-dns-am-i-using-in-ubuntu-12-04 -# Use nmcli dev list for older version nmcli -# Use nmcli dev show for newer version nmcli -nmcli dev show > $TMP -if [ $? -ne 0 ]; then # $? is the return code, if not 0 something bad happened. - echo "nmcli failed, trying older 'list' instead of 'show'" - nmcli dev list > $TMP - if [ $? -ne 0 ]; then - echo "nmcli failed again, giving up..." - exit 1 - fi -fi - -grep IP4.DNS $TMP | sed 's/IP4.DNS\[.\]:/nameserver/' >> /tmp/resolv.conf - -scp /tmp/resolv.conf root@$beagleAddr:/etc - -# Tell the beagle to use the host as the gateway. -ssh root@$beagleAddr "/sbin/route add default gw $hostAddr" || true - diff --git a/books/beaglebone-cookbook/05tips/tips.rst b/books/beaglebone-cookbook/05tips/tips.rst index 1e3e0b27..11feb0db 100644 --- a/books/beaglebone-cookbook/05tips/tips.rst +++ b/books/beaglebone-cookbook/05tips/tips.rst @@ -814,11 +814,11 @@ file called ``ipMasquerade.sh`` on your host computer. .. _tips_ipmasq_code: -.. literalinclude:: code/ipMasquerade.sh +.. literalinclude:: ../code/05tips/ipMasquerade.sh :caption: Code for IP Masquerading (ipMasquerade.sh) :linenos: -:download:`ipMasquerade.sh <code/ipMasquerade.sh>` +:download:`ipMasquerade.sh <../code/05tips/ipMasquerade.sh>` Then, on your host, run the following commands: @@ -836,11 +836,11 @@ in :ref:`tips_setDNS` to ``setDNS.sh`` on your host computer. .. _tips_setDNS: -.. literalinclude:: code/setDNS.sh +.. literalinclude:: ../code/05tips/setDNS.sh :caption: Code for setting the DNS on the Bone (setDNS.sh) :linenos: -:download:`setDNS.sh <code/setDNS.sh>` +:download:`setDNS.sh <../code/05tips/setDNS.sh>` Then, on your host, run the following commands: @@ -1320,11 +1320,11 @@ and is much faster. The approach is the same, write to the */sys/class/gpio* fi .. _misc_c_blink: -.. literalinclude:: code/blinkLED.c +.. literalinclude:: ../code/05tips/blinkLED.c :caption: Use C to blink an LED (blinkLED.c) :linenos: -:download:`blinkLED.c <code/blinkLED.c>` +:download:`blinkLED.c <../code/05tips/blinkLED.c>` Here, as with JavaScript and Python, the gpio pins are refered to by the Linux gpio number. :ref:`tips_cape_headers_digital` shows how the P8 and P9 Headers numbers map to the gpio number. diff --git a/books/beaglebone-cookbook/06iot/code/GPIOserver.js b/books/beaglebone-cookbook/06iot/code/GPIOserver.js deleted file mode 100755 index 00c28d9b..00000000 --- a/books/beaglebone-cookbook/06iot/code/GPIOserver.js +++ /dev/null @@ -1,59 +0,0 @@ -#!/usr/bin/env node -// Initial idea from Getting Started With node.js and socket.io -// http://codehenge.net/blog/2011/12/getting-started-with-node-js-and-socket-io- -// v0-7-part-2/ -// This is a simple server for the various web frontends -// Display status of P9_42 -"use strict"; - -var port = 9090, // Port on which to listen - http = require('http'), - url = require('url'), - fs = require('fs'), - b = require('bonescript'), - gpio = 'P9_42'; // gpio port to read - - // <1> -var htmlStart = "\ -<!DOCTYPE html>\ -<html>\ -<body>\ -\ -<h1>" + gpio + "</h1>\ -data = "; - - // <2> -var htmlEnd = "\ -</body>\ -</html>"; - -var server = http.createServer(servePage); - -b.pinMode(gpio, b.INPUT, 7, 'pulldown'); - -server.listen(port); -console.log("Listening on " + port); - -function servePage(req, res) { - var path = url.parse(req.url).pathname; - console.log("path: " + path); - if (path === '/gpio') { // <3> - var data = b.digitalRead(gpio); // <4> - res.write(htmlStart + data + htmlEnd, 'utf8'); // <5> - res.end(); - } else { - fs.readFile(__dirname + path, function (err, data) { - if (err) { - return send404(res); - } - res.write(data, 'utf8'); - res.end(); - }); - } -} - -function send404(res) { - res.writeHead(404); - res.write('404 - page not found'); - res.end(); -} diff --git a/books/beaglebone-cookbook/06iot/code/analogInContinuous.py b/books/beaglebone-cookbook/06iot/code/analogInContinuous.py deleted file mode 100755 index f026aa92..00000000 --- a/books/beaglebone-cookbook/06iot/code/analogInContinuous.py +++ /dev/null @@ -1,91 +0,0 @@ -#!/usr/bin/python -#////////////////////////////////////// -# analogInContinuous.py -# Read analog data via IIO continous mode and plots it. -#////////////////////////////////////// -# From: https://stackoverflow.com/questions/20295646/python-ascii-plots-in-terminal -# https://github.com/dkogan/gnuplotlib -# https://github.com/dkogan/gnuplotlib/blob/master/guide/guide.org -# sudo apt install gnuplot (10 minute to install) -# sudo apt install libatlas-base-dev -# pip3 install gnuplotlib -# This uses X11, so when connecting to the bone from the host use: ssh -X bone - -# See https://elinux.org/index.php?title=EBC_Exercise_10a_Analog_In#Analog_in_-_Continuous.2C_Change_the_sample_rate -# for instructions on changing the sampling rate. Can go up to 200KHz. - -fd = open(IIODEV, "r") -import numpy as np -import gnuplotlib as gp -import time -# import struct - -IIOPATH='/sys/bus/iio/devices/iio:device0' -IIODEV='/dev/iio:device0' -LEN = 100 -SAMPLERATE=8000 -AIN='2' - -# Setup IIO for Continous reading -# Enable AIN -try: - file1 = open(IIOPATH+'/scan_elements/in_voltage'+AIN+'_en', 'w') - file1.write('1') - file1.close() -except: # carry on if it's already enabled - pass -# Set buffer length -file1 = open(IIOPATH+'/buffer/length', 'w') -file1.write(str(2*LEN)) # I think LEN is in 16-bit values, but here we pass bytes -file1.close() -# Enable continous -file1 = open(IIOPATH+'/buffer/enable', 'w') -file1.write('1') -file1.close() - -x = np.linspace(0, 1000*LEN/SAMPLERATE, LEN) -# Do a dummy plot to give time of the fonts to load. -gp.plot(x, x) -print("Waiting for fonts to load") -time.sleep(10) - -print('Hit ^C to stop') - -fd = open(IIODEV, "r") - -try: - while True: - y = np.fromfile(fd, dtype='uint16', count=LEN)*1.8/4096 - # print(y) - gp.plot(x, y, - xlabel = 't (ms)', - ylabel = 'volts', - _yrange = [0, 2], - title = 'analogInContinuous', - legend = np.array( ("P9.39", ), ), - # ascii=1, - # terminal="xterm", - # legend = np.array( ("P9.40", "P9.38"), ), - # _with = 'lines' - ) - -except KeyboardInterrupt: - print("Turning off input.") - # Disable continous - file1 = open(IIOPATH+'/buffer/enable', 'w') - file1.write('0') - file1.close() - - file1 = open(IIOPATH+'/scan_elements/in_voltage'+AIN+'_en', 'w') - file1.write('0') - file1.close() - -# // Bone | Pocket | AIN -# // ----- | ------ | --- -# // P9_39 | P1_19 | 0 -# // P9_40 | P1_21 | 1 -# // P9_37 | P1_23 | 2 -# // P9_38 | P1_25 | 3 -# // P9_33 | P1_27 | 4 -# // P9_36 | P2_35 | 5 -# // P9_35 | P1_02 | 6 diff --git a/books/beaglebone-cookbook/06iot/code/emailTest.py b/books/beaglebone-cookbook/06iot/code/emailTest.py deleted file mode 100755 index 4c696b7c..00000000 --- a/books/beaglebone-cookbook/06iot/code/emailTest.py +++ /dev/null @@ -1,24 +0,0 @@ -#!/usr/bin/env python -# From: https://realpython.com/python-send-email/ -import smtplib, ssl - -port = 587 # For starttls -smtp_server = "smtp.gmail.com" -sender_email = "from_account@gmail.com" -receiver_email = "to_account@gmail.com" -# Go to: https://myaccount.google.com/security -# Select App password -# Generate your own 16 char password, copy here -# Delete password when done -password = "cftqhcejjdjfdwjh" -message = """\ -Subject: Testing email - -This message is sent from Python. - -""" -context = ssl.create_default_context() -with smtplib.SMTP(smtp_server, port) as server: - server.starttls(context=context) - server.login(sender_email, password) - server.sendmail(sender_email, receiver_email, message) diff --git a/books/beaglebone-cookbook/06iot/code/flask/app1.py b/books/beaglebone-cookbook/06iot/code/flask/app1.py deleted file mode 100755 index 7a0597c5..00000000 --- a/books/beaglebone-cookbook/06iot/code/flask/app1.py +++ /dev/null @@ -1,22 +0,0 @@ -#!/usr/bin/env python -# From: https://towardsdatascience.com/python-webserver-with-flask-and-raspberry-pi-398423cc6f5d - -''' -Code created by Matt Richardson -for details, visit: http://mattrichardson.com/Raspberry-Pi-Flask/inde... -''' -from flask import Flask, render_template -import datetime -app = Flask(__name__) -@app.route("/") -def hello(): - now = datetime.datetime.now() - timeString = now.strftime("%Y-%m-%d %H:%M") - templateData = { - 'title' : 'HELLO!', - 'time': timeString - } - return render_template('index1.html', **templateData) -if __name__ == "__main__": - app.run(host='0.0.0.0', port=8080, debug=True) - \ No newline at end of file diff --git a/books/beaglebone-cookbook/06iot/code/flask/app2.py b/books/beaglebone-cookbook/06iot/code/flask/app2.py deleted file mode 100755 index a6f026cd..00000000 --- a/books/beaglebone-cookbook/06iot/code/flask/app2.py +++ /dev/null @@ -1,36 +0,0 @@ -#!/usr/bin/env python -# From: https://towardsdatascience.com/python-webserver-with-flask-and-raspberry-pi-398423cc6f5d -import os -from flask import Flask, render_template -app = Flask(__name__) - -pin = '30' # P9_11 is gpio 30 -GPIOPATH="/sys/class/gpio" -buttonSts = 0 - -# Make sure pin is exported -if (not os.path.exists(GPIOPATH+"/gpio"+pin)): - f = open(GPIOPATH+"/export", "w") - f.write(pin) - f.close() - -# Make it an input pin -f = open(GPIOPATH+"/gpio"+pin+"/direction", "w") -f.write("in") -f.close() - -@app.route("/") -def index(): - # Read Button Status - f = open(GPIOPATH+"/gpio"+pin+"/value", "r") - buttonSts = f.read()[:-1] - f.close() - - # buttonSts = GPIO.input(button) - templateData = { - 'title' : 'GPIO input Status!', - 'button' : buttonSts, - } - return render_template('index2.html', **templateData) -if __name__ == "__main__": - app.run(host='0.0.0.0', port=8080, debug=True) \ No newline at end of file diff --git a/books/beaglebone-cookbook/06iot/code/flask/app3.py b/books/beaglebone-cookbook/06iot/code/flask/app3.py deleted file mode 100755 index 388206d5..00000000 --- a/books/beaglebone-cookbook/06iot/code/flask/app3.py +++ /dev/null @@ -1,60 +0,0 @@ -#!/usr/bin/env python -# From: https://towardsdatascience.com/python-webserver-with-flask-and-raspberry-pi-398423cc6f5d -# import Adafruit_BBIO.GPIO as GPIO -import os -from flask import Flask, render_template, request -app = Flask(__name__) -#define LED GPIO -ledRed = "P9_14" -pin = '50' # P9_14 is gpio 50 -GPIOPATH="/sys/class/gpio" - -#initialize GPIO status variable -ledRedSts = 0 -# Make sure pin is exported -if (not os.path.exists(GPIOPATH+"/gpio"+pin)): - f = open(GPIOPATH+"/export", "w") - f.write(pin) - f.close() -# Define led pin as output -f = open(GPIOPATH+"/gpio"+pin+"/direction", "w") -f.write("out") -f.close() -# turn led OFF -f = open(GPIOPATH+"/gpio"+pin+"/value", "w") -f.write("0") -f.close() - -@app.route("/") -def index(): - # Read Sensors Status - f = open(GPIOPATH+"/gpio"+pin+"/value", "r") - ledRedSts = f.read() - f.close() - templateData = { - 'title' : 'GPIO output Status!', - 'ledRed' : ledRedSts, - } - return render_template('index3.html', **templateData) - -@app.route("/<deviceName>/<action>") -def action(deviceName, action): - if deviceName == 'ledRed': - actuator = ledRed - f = open(GPIOPATH+"/gpio"+pin+"/value", "w") - if action == "on": - f.write("1") - if action == "off": - f.write("0") - f.close() - - f = open(GPIOPATH+"/gpio"+pin+"/value", "r") - ledRedSts = f.read() - f.close() - - templateData = { - 'ledRed' : ledRedSts, - } - return render_template('index3.html', **templateData) -if __name__ == "__main__": - app.run(host='0.0.0.0', port=8080, debug=True) \ No newline at end of file diff --git a/books/beaglebone-cookbook/06iot/code/flask/app4.py b/books/beaglebone-cookbook/06iot/code/flask/app4.py deleted file mode 100755 index 9799ff3d..00000000 --- a/books/beaglebone-cookbook/06iot/code/flask/app4.py +++ /dev/null @@ -1,79 +0,0 @@ -#!/usr/bin/env python -# From: https://towardsdatascience.com/python-webserver-with-flask-and-raspberry-pi-398423cc6f5d -import os -# import Adafruit_BBIO.GPIO as GPIO -from flask import Flask, render_template, request -app = Flask(__name__) -GPIOPATH="/sys/class/gpio" -#define sensors GPIOs -button = "30" # "P9_11" -#define actuators GPIOs -ledRed = "50" # "P9_14" - -# Make sure pin is exported -if (not os.path.exists(GPIOPATH+"/gpio"+button)): - f = open(GPIOPATH+"/export", "w") - f.write(pin) - f.close() -if (not os.path.exists(GPIOPATH+"/gpio"+ledRed)): - f = open(GPIOPATH+"/export", "w") - f.write(pin) - f.close() -#initialize GPIO status variables -buttonSts = 0 -ledRedSts = 0 -# Define button and PIR sensor pins as an input -f = open(GPIOPATH+"/gpio"+button+"/direction", "w") -f.write("in") -f.close() -# Define led pins as output -f = open(GPIOPATH+"/gpio"+ledRed+"/direction", "w") -f.write("out") -f.close() -# turn leds OFF -f = open(GPIOPATH+"/gpio"+ledRed+"/value", "w") -f.write("0") -f.close() - -@app.route("/") -def index(): - # Read GPIO Status - f = open(GPIOPATH+"/gpio"+button+"/value", "r") - buttonSts = f.read()[:-1] - f.close() - f = open(GPIOPATH+"/gpio"+ledRed+"/value", "r") - ledRedSts = f.read()[:-1] - f.close() - - templateData = { - 'button' : buttonSts, - 'ledRed' : ledRedSts, - } - return render_template('index4.html', **templateData) - -@app.route("/<deviceName>/<action>") -def action(deviceName, action): - if deviceName == 'ledRed': - actuator = ledRed - - f = open(GPIOPATH+"/gpio"+ledRed+"/value", "w") - if action == "on": - f.write("1") - if action == "off": - f.write("0") - f.close() - - f = open(GPIOPATH+"/gpio"+button+"/value", "r") - buttonSts = f.read()[:-1] - f.close() - f = open(GPIOPATH+"/gpio"+ledRed+"/value", "r") - ledRedSts = int(f.read()[:-1]) - f.close() - - templateData = { - 'button' : buttonSts, - 'ledRed' : ledRedSts, - } - return render_template('index4.html', **templateData) -if __name__ == "__main__": - app.run(host='0.0.0.0', port=8080, debug=True) \ No newline at end of file diff --git a/books/beaglebone-cookbook/06iot/code/flask/app5.py b/books/beaglebone-cookbook/06iot/code/flask/app5.py deleted file mode 100755 index d92a2583..00000000 --- a/books/beaglebone-cookbook/06iot/code/flask/app5.py +++ /dev/null @@ -1,87 +0,0 @@ -#!/usr/bin/env python -# From: https://towardsdatascience.com/python-webserver-with-flask-and-raspberry-pi-398423cc6f5d -import os -# import Adafruit_BBIO.GPIO as GPIO -from flask import Flask, render_template, request -app = Flask(__name__) -GPIOPATH="/sys/class/gpio" -#define sensors GPIOs -button = "30" # "P9_11" -#define actuators GPIOs -ledRed = "50" # "P9_14" - -# Make sure pin is exported -if (not os.path.exists(GPIOPATH+"/gpio"+button)): - f = open(GPIOPATH+"/export", "w") - f.write(pin) - f.close() -if (not os.path.exists(GPIOPATH+"/gpio"+ledRed)): - f = open(GPIOPATH+"/export", "w") - f.write(pin) - f.close() -#initialize GPIO status variables -buttonSts = 0 -ledRedSts = 0 -# Define button and PIR sensor pins as an input -f = open(GPIOPATH+"/gpio"+button+"/direction", "w") -f.write("in") -f.close() -# Define led pins as output -f = open(GPIOPATH+"/gpio"+ledRed+"/direction", "w") -f.write("out") -f.close() -# turn leds OFF -f = open(GPIOPATH+"/gpio"+ledRed+"/value", "w") -f.write("0") -f.close() - -@app.route("/") -def index(): - # Read GPIO Status - f = open(GPIOPATH+"/gpio"+button+"/value", "r") - buttonSts = f.read()[:-1] - f.close() - f = open(GPIOPATH+"/gpio"+ledRed+"/value", "r") - ledRedSts = f.read()[:-1] - f.close() - - templateData = { - 'button' : buttonSts, - 'ledRed' : ledRedSts, - } - return render_template('index5.html', **templateData) - -@app.route("/<deviceName>/<action>") -def action(deviceName, action): - if deviceName == 'ledRed': - actuator = ledRed - - f = open(GPIOPATH+"/gpio"+ledRed+"/value", "w") - if action == "on": - f.write("1") - if action == "off": - f.write("0") - if action == "toggle": - f.close() - f = open(GPIOPATH+"/gpio"+ledRed+"/value", "r") - ledRedSts = int(f.read()[:-1]) - ledRedSts = str(int(not ledRedSts)) - f.close() - f = open(GPIOPATH+"/gpio"+ledRed+"/value", "w") - f.write(ledRedSts) - f.close() - - f = open(GPIOPATH+"/gpio"+button+"/value", "r") - buttonSts = f.read()[:-1] - f.close() - f = open(GPIOPATH+"/gpio"+ledRed+"/value", "r") - ledRedSts = int(f.read()[:-1]) - f.close() - - templateData = { - 'button' : buttonSts, - 'ledRed' : ledRedSts, - } - return render_template('index5.html', **templateData) -if __name__ == "__main__": - app.run(host='0.0.0.0', port=8080, debug=True) \ No newline at end of file diff --git a/books/beaglebone-cookbook/06iot/code/flask/flask.service b/books/beaglebone-cookbook/06iot/code/flask/flask.service deleted file mode 100644 index 1b577785..00000000 --- a/books/beaglebone-cookbook/06iot/code/flask/flask.service +++ /dev/null @@ -1,10 +0,0 @@ -[Unit] -Description=flask server - -[Service] -WorkingDirectory=/home/debian/exercises/flask/server -ExecStart=/home/debian/exercises/flask/server/app5.py -SyslogIdentifier=flask - -[Install] -WantedBy=multi-user.target diff --git a/books/beaglebone-cookbook/06iot/code/flask/helloWorld.py b/books/beaglebone-cookbook/06iot/code/flask/helloWorld.py deleted file mode 100755 index 176350b0..00000000 --- a/books/beaglebone-cookbook/06iot/code/flask/helloWorld.py +++ /dev/null @@ -1,10 +0,0 @@ -#!/usr/bin/env python -# From: https://towardsdatascience.com/python-webserver-with-flask-and-raspberry-pi-398423cc6f5d - -from flask import Flask -app = Flask(__name__) -@app.route('/') -def index(): - return 'hello, world' -if __name__ == '__main__': - app.run(debug=True, port=8080, host='0.0.0.0') \ No newline at end of file diff --git a/books/beaglebone-cookbook/06iot/code/flask/install.sh b/books/beaglebone-cookbook/06iot/code/flask/install.sh deleted file mode 100644 index 33224469..00000000 --- a/books/beaglebone-cookbook/06iot/code/flask/install.sh +++ /dev/null @@ -1,7 +0,0 @@ -# From: https://www.cloudsavvyit.com/903/debug-your-local-applications-over-the-internet-with-ngrok-tunnels/ -wget https://bin.equinox.io/c/4VmDzA7iaHb/ngrok-stable-linux-arm.zip -unzip ngrok-stable-linux-arm.zip -sudo mv ngrok ~/.local/bin - -mkdir -p ~/.ngrok2 -cp ngrok.yml ~/.ngrok2 \ No newline at end of file diff --git a/books/beaglebone-cookbook/06iot/code/flask/ngrok.yml b/books/beaglebone-cookbook/06iot/code/flask/ngrok.yml deleted file mode 100644 index 5074663e..00000000 --- a/books/beaglebone-cookbook/06iot/code/flask/ngrok.yml +++ /dev/null @@ -1,4 +0,0 @@ -tunnels: - flask: - proto: http - addr: 8081 diff --git a/books/beaglebone-cookbook/06iot/code/flask/setup.sh b/books/beaglebone-cookbook/06iot/code/flask/setup.sh deleted file mode 100644 index 410868a7..00000000 --- a/books/beaglebone-cookbook/06iot/code/flask/setup.sh +++ /dev/null @@ -1,2 +0,0 @@ -# Start ngrok -ngrok start flask diff --git a/books/beaglebone-cookbook/06iot/code/flask/static/favicon.ico b/books/beaglebone-cookbook/06iot/code/flask/static/favicon.ico deleted file mode 100644 index e96154d507400f4d1ad0c844a47f9d3455af3917..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 562718 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%0D(^_d3Z}p4N_j1z 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 diff --git a/books/beaglebone-cookbook/06iot/code/flask/static/style.css b/books/beaglebone-cookbook/06iot/code/flask/static/style.css deleted file mode 100644 index f05f2cc8..00000000 --- a/books/beaglebone-cookbook/06iot/code/flask/static/style.css +++ /dev/null @@ -1,15 +0,0 @@ -/*body {*/ -/* background: blue;*/ -/* color: yellow;*/ -/*}*/ -.button { - font: bold 15px Arial; - text-decoration: none; - background-color: #EEEEEE; - color: #333333; - padding: 2px 6px 2px 6px; - border-top: 1px solid #CCCCCC; - border-right: 1px solid #333333; - border-bottom: 1px solid #333333; - border-left: 1px solid #CCCCCC; -} \ No newline at end of file diff --git a/books/beaglebone-cookbook/06iot/code/flask/templates/index1.html b/books/beaglebone-cookbook/06iot/code/flask/templates/index1.html deleted file mode 100644 index 067d7eff..00000000 --- a/books/beaglebone-cookbook/06iot/code/flask/templates/index1.html +++ /dev/null @@ -1,9 +0,0 @@ -<!DOCTYPE html> - <head> - <title>{{ title }}</title> - </head> - <body> - <h1>Hello, World!</h1> - <h2>The date and time on the server is: {{ time }}</h2> - </body> -</html> diff --git a/books/beaglebone-cookbook/06iot/code/flask/templates/index2.html b/books/beaglebone-cookbook/06iot/code/flask/templates/index2.html deleted file mode 100644 index be37dfc4..00000000 --- a/books/beaglebone-cookbook/06iot/code/flask/templates/index2.html +++ /dev/null @@ -1,10 +0,0 @@ -<!DOCTYPE html> - <head> - <title>{{ title }}</title> - <link rel="stylesheet" href='../static/style.css'/> - </head> - <body> - <h1>{{ title }}</h1> - <h2>Button pressed: {{ button }}</h1> - </body> -</html> diff --git a/books/beaglebone-cookbook/06iot/code/flask/templates/index3.html b/books/beaglebone-cookbook/06iot/code/flask/templates/index3.html deleted file mode 100644 index ef95fca7..00000000 --- a/books/beaglebone-cookbook/06iot/code/flask/templates/index3.html +++ /dev/null @@ -1,17 +0,0 @@ -<!DOCTYPE html> - <head> - <title>GPIO Control</title> - <link rel="stylesheet" href='../static/style.css'/> - </head> - <body> - <h2>Actuators</h2> - <h3> Status </h3> - RED LED ==> {{ ledRed }} - <br> - <h3> Commands </h3> - RED LED Ctrl ==> - <a href="/ledRed/on" class="button">TURN ON</a> - <a href="/ledRed/off"class="button">TURN OFF</a> - </body> -</html> - diff --git a/books/beaglebone-cookbook/06iot/code/flask/templates/index4.html b/books/beaglebone-cookbook/06iot/code/flask/templates/index4.html deleted file mode 100644 index ea85a3f3..00000000 --- a/books/beaglebone-cookbook/06iot/code/flask/templates/index4.html +++ /dev/null @@ -1,20 +0,0 @@ -<!DOCTYPE html> - <head> - <title>GPIO Control</title> - <link rel="stylesheet" href='../static/style.css'/> - </head> - <body> - <h1>GPIO Control</h1> - <h2> Sensor Status </h2> - <h3> BUTTON ==> {{ button }}</h3> - <h2> Actuator Status & Control </h2> - <h3> RED LED ==> {{ ledRed }} ==> - {% if ledRed == 1 %} - <a href="/ledRed/off"class="button">TURN OFF</a> - {% else %} - <a href="/ledRed/on" class="button">TURN ON</a> - {% endif %} - </h3> - </h3> - </body> -</html> \ No newline at end of file diff --git a/books/beaglebone-cookbook/06iot/code/flask/templates/index5.html b/books/beaglebone-cookbook/06iot/code/flask/templates/index5.html deleted file mode 100644 index cff4bffb..00000000 --- a/books/beaglebone-cookbook/06iot/code/flask/templates/index5.html +++ /dev/null @@ -1,21 +0,0 @@ -<!DOCTYPE html> - <head> - <title>GPIO Control</title> - <link rel="stylesheet" href='../static/style.css'/> - </head> - <body> - <h1>GPIO Control</h1> - <h2> Sensor Status </h2> - <h3> BUTTON ==> {{ button }}</h3> - <h2> Actuator Status & Control </h2> - <h3> RED LED ==> {{ ledRed }} ==> - <a href="/ledRed/toggle" class="button">TOGGLE</a> - {% if ledRed == 1 %} - <a href="/ledRed/off"class="button">TURN OFF</a> - {% else %} - <a href="/ledRed/on" class="button">TURN ON</a> - {% endif %} - </h3> - </h3> - </body> -</html> \ No newline at end of file diff --git a/books/beaglebone-cookbook/06iot/code/flotDemo.html b/books/beaglebone-cookbook/06iot/code/flotDemo.html deleted file mode 100644 index 8bf03881..00000000 --- a/books/beaglebone-cookbook/06iot/code/flotDemo.html +++ /dev/null @@ -1,15 +0,0 @@ -<html> - <head> - <title>BoneScript Flot Demo</title> - <script src="/static/flot/jquery.min.js"></script> - <script src="/static/flot/jquery.flot.min.js"></script> - <script src="/static/bonescript.js"></script> - <script src="flotDemo.js"></script> - </head> -<body> - -<h1>BoneScript Flot Demo</h1> -<div id="myplot" style="width:500px;height:300px;"></div> - -</body> -</html> diff --git a/books/beaglebone-cookbook/06iot/code/flotDemo.js b/books/beaglebone-cookbook/06iot/code/flotDemo.js deleted file mode 100644 index 5bf690c2..00000000 --- a/books/beaglebone-cookbook/06iot/code/flotDemo.js +++ /dev/null @@ -1,66 +0,0 @@ -setTargetAddress('192.168.7.2', { // <1> - initialized: run -}); - -function run() { - var b = require('bonescript'); // <2> - var POT = 'P9_36'; // <3> - - var container = $("#myplot"); // <4> - var totalPoints = container.outerWidth() / 2 || 250; // <5> - var data = []; - var plotOptions = { // <6> - series: { - shadowSize: 0 - }, - yaxis: { - min: 0, - max: 1 - }, - xaxis: { - min: 0, - max: totalPoints, - show: false - } - }; - var plot = $.plot(container, getData(), plotOptions); // <7> - - drawGraph(); // <8> - - function drawGraph() { // <9> - plot.setData(getData()); - plot.draw(); - b.analogRead(POT, onAnalogRead); - } - - // Handle data back from potentiometer - function onAnalogRead(x) { - if (!x.err && typeof x.value == 'number') { - pushData(x.value); // <10> - } - setTimeout(drawGraph, 20); // <11> - } - - function pushData(y) { - if (data.length && (data.length + 1) > totalPoints) { - data = data.slice(1); - } - if (data.length < totalPoints) { - data.push(y); - } - } - - function getData() { - var res = []; - for (var i = 0; i < data.length; ++i) { - res.push([i, data[i]]); - } - var series = [{ - data: res, - lines: { - fill: true - } - }]; - return series; - } -} \ No newline at end of file diff --git a/books/beaglebone-cookbook/06iot/code/jQueryDemo.js b/books/beaglebone-cookbook/06iot/code/jQueryDemo.js deleted file mode 100644 index 9581030e..00000000 --- a/books/beaglebone-cookbook/06iot/code/jQueryDemo.js +++ /dev/null @@ -1,34 +0,0 @@ -setTargetAddress('192.168.7.2', { // <1> - initialized: run -}); - -function run() { - var b = require('bonescript'); // <2> - var SLIDER = 'P9_36'; // <3> - var BUTTON = 'P8_19'; - b.pinMode(BUTTON, b.INPUT); - - getSliderStatus(); // <4> - - function getSliderStatus() { - b.analogRead(SLIDER, onSliderRead); // <5> - } - - function onSliderRead(x) { - if (!x.err) { // <6> - $('#sliderStatus').html(x.value.toFixed(3)); - } - getButtonStatus() // <7> - } - - function getButtonStatus() { - b.digitalRead(BUTTON, onButtonRead); // <8> - } - - function onButtonRead(x) { - if (!x.err) { // <9> - $('#buttonStatus').html(x.value); - } - setTimeout(getSliderStatus, 20); // <10> - } -} diff --git a/books/beaglebone-cookbook/06iot/code/jQueryInstall.sh b/books/beaglebone-cookbook/06iot/code/jQueryInstall.sh deleted file mode 100644 index 8f5e8b1e..00000000 --- a/books/beaglebone-cookbook/06iot/code/jQueryInstall.sh +++ /dev/null @@ -1,2 +0,0 @@ -# This gives easy acces to the bonscript and jquery libraries -ln -s /var/lib/cloud9/static/ . diff --git a/books/beaglebone-cookbook/06iot/code/launchPad.js b/books/beaglebone-cookbook/06iot/code/launchPad.js deleted file mode 100755 index f81591dd..00000000 --- a/books/beaglebone-cookbook/06iot/code/launchPad.js +++ /dev/null @@ -1,37 +0,0 @@ -#!/usr/bin/env node -// Need to add exports.serialParsers = m.module.parsers; -// to /usr/local/lib/node_modules/bonescript/serial.js -var b = require('bonescript'); - -var port = '/dev/ttyO1'; // <1> -var options = { - baudrate: 9600, // <2> - parser: b.serialParsers.readline("\n") // <3> -}; - -b.serialOpen(port, options, onSerial); // <4> - -function onSerial(x) { // <5> - console.log(x.event); - if (x.err) { - console.log('***ERROR*** ' + JSON.stringify(x)); - } - if (x.event == 'open') { - console.log('***OPENED***'); - setInterval(sendCommand, 1000); // <6> - } - if (x.event == 'data') { - console.log(String(x.data)); - } -} - -var command = ['r', 'g']; // <7> -var commIdx = 1; - -function sendCommand() { - // console.log('Command: ' + command[commIdx]); - b.serialWrite(port, command[commIdx++]); // <8> - if(commIdx >= command.length) { // <9> - commIdx = 0; - } -} diff --git a/books/beaglebone-cookbook/06iot/code/launchPad/launchPad.ino b/books/beaglebone-cookbook/06iot/code/launchPad/launchPad.ino deleted file mode 100644 index 12e3cd7d..00000000 --- a/books/beaglebone-cookbook/06iot/code/launchPad/launchPad.ino +++ /dev/null @@ -1,44 +0,0 @@ -/* - Tests connection to a BeagleBone - Mark A. Yoder - Waits for input on Serial Port - g - Green toggle - r - Red toggle -*/ -char inChar = 0; // incoming serial byte -int red = 0; -int green = 0; - -void setup() -{ - // initialize the digital pin as an output. - pinMode(RED_LED, OUTPUT); // <1> - pinMode(GREEN_LED, OUTPUT); - // start serial port at 9600 bps: - Serial.begin(9600); // <2> - Serial.print("Command (r, g): "); // <3> - - digitalWrite(GREEN_LED, green); // <4> - digitalWrite( RED_LED, red); -} - -void loop() -{ - if(Serial.available() > 0 ) { // <5> - inChar = Serial.read(); - switch(inChar) { // <6> - case 'g': - green = ~green; - digitalWrite(GREEN_LED, green); - Serial.println("Green"); - break; - case 'r': - red = ~red; - digitalWrite(RED_LED, red); - Serial.println("Red"); - break; - } - Serial.print("Command (r, g): "); - } -} - diff --git a/books/beaglebone-cookbook/06iot/code/nodemailer-install.sh b/books/beaglebone-cookbook/06iot/code/nodemailer-install.sh deleted file mode 100755 index 856fc7c3..00000000 --- a/books/beaglebone-cookbook/06iot/code/nodemailer-install.sh +++ /dev/null @@ -1 +0,0 @@ -npm install -g nodemailer diff --git a/books/beaglebone-cookbook/06iot/code/nodemailer-test.js b/books/beaglebone-cookbook/06iot/code/nodemailer-test.js deleted file mode 100755 index e5b99f6d..00000000 --- a/books/beaglebone-cookbook/06iot/code/nodemailer-test.js +++ /dev/null @@ -1,38 +0,0 @@ -#!/usr/bin/env node -// From: https://github.com/andris9/Nodemailer - -var nodemailer = require('nodemailer'); - -// create reusable transporter object using SMTP transport -var transporter = nodemailer.createTransport({ - service: 'gmail', - auth: { - user: 'yourUser@gmail.com', - pass: 'yourPass' - } -}); - -// NB! No need to re-create the transporter object. You can use -// the same transporter object for all e-mails - -// set up e-mail data with unicode symbols -var mailOptions = { - from: 'Your User <yourUser@gmail.edu>', // sender address - to: 'anotherUser@gmail.edu', // list of receivers - subject: 'Test of nodemail', // Subject line - text: 'Hello world from modemailer', // plaintext body - html: '<b>Hello world</b><p>Way to go!</p>' // html body -}; - -// send mail with defined transport object -transporter.sendMail(mailOptions, function(error, info){ - if(error){ - console.log(error); - }else{ - console.log('Message sent: ' + info.response); - } -}); - -// Nodemailer is licensed under MIT license -// (https://github.com/andris9/Nodemailer/blob/master/LICENSE). -// Basically you can do whatever you want to with it diff --git a/books/beaglebone-cookbook/06iot/code/noderedExample.json b/books/beaglebone-cookbook/06iot/code/noderedExample.json deleted file mode 100644 index 06b306df..00000000 --- a/books/beaglebone-cookbook/06iot/code/noderedExample.json +++ /dev/null @@ -1,164 +0,0 @@ -[ - { - "id": "70fd05e2.f03d0c", - "type": "tab", - "label": "Flow 1", - "disabled": false, - "info": "" - }, - { - "id": "b1dc9221.09e41", - "type": "gpio out", - "z": "70fd05e2.f03d0c", - "name": "", - "state": "OUTPUT", - "pin": "P9_14", - "i2cDelay": "0", - "i2cAddress": "", - "i2cRegister": "", - "outputs": 0, - "board": "14fb0dec.376712", - "x": 610, - "y": 180, - "wires": [] - }, - { - "id": "acb4df30.72216", - "type": "inject", - "z": "70fd05e2.f03d0c", - "name": "", - "props": [ - { - "p": "payload" - } - ], - "repeat": "", - "crontab": "", - "once": false, - "onceDelay": 0.1, - "topic": "", - "payload": "1", - "payloadType": "num", - "x": 370, - "y": 180, - "wires": [ - [ - "b1dc9221.09e41" - ] - ] - }, - { - "id": "35e9479e.0e2428", - "type": "inject", - "z": "70fd05e2.f03d0c", - "name": "", - "props": [ - { - "p": "payload" - } - ], - "repeat": "", - "crontab": "", - "once": false, - "onceDelay": 0.1, - "topic": "", - "payload": "0", - "payloadType": "str", - "x": 370, - "y": 220, - "wires": [ - [ - "b1dc9221.09e41" - ] - ] - }, - { - "id": "cca6a964.c0e978", - "type": "gpio out", - "z": "70fd05e2.f03d0c", - "name": "", - "state": "OUTPUT", - "pin": "USR3", - "i2cDelay": "0", - "i2cAddress": "", - "i2cRegister": "", - "outputs": 0, - "board": "14fb0dec.376712", - "x": 610, - "y": 280, - "wires": [] - }, - { - "id": "b9def222.f9a97", - "type": "inject", - "z": "70fd05e2.f03d0c", - "name": "", - "props": [ - { - "p": "payload" - } - ], - "repeat": "", - "crontab": "", - "once": false, - "onceDelay": 0.1, - "topic": "", - "payload": "1", - "payloadType": "num", - "x": 370, - "y": 280, - "wires": [ - [ - "cca6a964.c0e978" - ] - ] - }, - { - "id": "230706ad.dbc7ea", - "type": "inject", - "z": "70fd05e2.f03d0c", - "name": "", - "props": [ - { - "p": "payload" - } - ], - "repeat": "", - "crontab": "", - "once": false, - "onceDelay": 0.1, - "topic": "", - "payload": "0", - "payloadType": "str", - "x": 370, - "y": 320, - "wires": [ - [ - "cca6a964.c0e978" - ] - ] - }, - { - "id": "14fb0dec.376712", - "type": "ioplugin", - "name": "", - "username": "", - "password": "", - "boardType": "beaglebone-io", - "serialportName": "", - "connectionType": "local", - "mqttServer": "", - "pubTopic": "", - "subTopic": "", - "tcpHost": "", - "tcpPort": "", - "sparkId": "", - "sparkToken": "", - "beanId": "", - "impId": "", - "uuid": "", - "token": "", - "sendUuid": "", - "samplingInterval": "500" - } -] \ No newline at end of file diff --git a/books/beaglebone-cookbook/06iot/code/processingDemo.js b/books/beaglebone-cookbook/06iot/code/processingDemo.js deleted file mode 100644 index 3356cc00..00000000 --- a/books/beaglebone-cookbook/06iot/code/processingDemo.js +++ /dev/null @@ -1,89 +0,0 @@ -var canvas = document.getElementById("mysketch"); -var p = new Processing(canvas, sketchProc); - -function sketchProc(pjs) { - // Sketch global variables - var radius = 50.0; - var X, Y; - var nX, nY; - var delay = 16; - var brightness = 0; - var buttonStatus = 0; - var sliderStatus = 0; - var lastSliderValue = 0; - var BUTTON = 'P8_19'; - var POT = 'P9_36'; - - // Get the BoneScript library and begin updating the canvas - setTargetAddress('beaglebone.local', { - initialized: run - }); - setTargetAddress('192.168.7.2', { - initialized: run - }); - - function run() { - var b = require('bonescript'); - b.pinMode(BUTTON, b.INPUT); - - // Setup the Processing Canvas - pjs.setup = function () { - pjs.size(256, 256); - pjs.strokeWeight(10); - pjs.frameRate(15); - X = pjs.width / 2; - Y = pjs.height / 2; - nX = X; - nY = Y; - } - - // Main draw loop - pjs.draw = function () { - // Calculate some fading values based on the frame count - radius = 50.0 + (15 - sliderStatus) * pjs.sin(pjs.frameCount / 4); - brightness = (radius - 40.0) / 20.0; - - // Track circle to new destination - X += (nX - X) / delay; - Y += (nY - Y) / delay; - - // Fill canvas grey - pjs.background(100); - - // Set fill-color to blue or red, based on button status - if (buttonStatus) pjs.fill(200, 30, 20) - else pjs.fill(0, 121, 184); - - // Set stroke-color white - pjs.stroke(255); - - // Draw circle - pjs.ellipse(X, Y, radius, radius); - - // Fetch slider location for next time - b.analogRead(POT, onAnalogRead); - - // Fetch button status - b.digitalRead(BUTTON, onDigitalRead); - } - - // Get things started - pjs.setup(); - - // Handle data back from potentiometer - function onAnalogRead(x) { - if (!x.err && (x.value >= 0) && (x.value <= 1)) { - if (Math.abs(x.value - lastSliderValue) > 0.05) { - lastSliderValue = x.value; - nY = x.value * 255; - sliderStatus = parseInt(x.value * 10, 10); - } - } - } - - // Handle data back from button - function onDigitalRead(x) { - buttonStatus = (x.value == b.LOW) ? 1 : 0; - } - } -} \ No newline at end of file diff --git a/books/beaglebone-cookbook/06iot/code/server.js b/books/beaglebone-cookbook/06iot/code/server.js deleted file mode 100755 index c827116c..00000000 --- a/books/beaglebone-cookbook/06iot/code/server.js +++ /dev/null @@ -1,37 +0,0 @@ -#!/usr/bin/env node -// Initial idea from Getting Started With node.js and socket.io -// by Constantine Aaron Cois, Ph.D. (www.codehenge.net) -// http://codehenge.net/blog/2011/12/getting-started-with-node-js-and-socket-io- -// v0-7-part-2/ -// This is a simple server for the various web frontends -"use strict"; - -var port = 9090, // Port on which to listen - http = require('http'), - url = require('url'), - fs = require('fs'), - b = require('bonescript'); - -var server = http.createServer(servePage); // <1> - -server.listen(port); // <2> -console.log("Listening on " + port); - -function servePage(req, res) { - var path = url.parse(req.url).pathname; // <3> - console.log("path: " + path); - - fs.readFile(__dirname + path, function (err, data) {// <4> - if (err) { // <5> - return send404(res); - } - res.write(data, 'utf8'); // <6> - res.end(); - }); -} - -function send404(res) { - res.writeHead(404); - res.write('404 - page not found'); - res.end(); -} diff --git a/books/beaglebone-cookbook/06iot/code/test.html b/books/beaglebone-cookbook/06iot/code/test.html deleted file mode 100644 index ddb20a32..00000000 --- a/books/beaglebone-cookbook/06iot/code/test.html +++ /dev/null @@ -1,10 +0,0 @@ -<!DOCTYPE html> -<html> -<body> - -<h1>My First Heading</h1> - -<p>My first paragraph.</p> - -</body> -</html> diff --git a/books/beaglebone-cookbook/06iot/code/twilio-test.js b/books/beaglebone-cookbook/06iot/code/twilio-test.js deleted file mode 100755 index 49ef9b58..00000000 --- a/books/beaglebone-cookbook/06iot/code/twilio-test.js +++ /dev/null @@ -1,39 +0,0 @@ -#!/usr/bin/env node -// From: http://twilio.github.io/twilio-node/ -// Twilio Credentials -var accountSid = ''; -var authToken = ''; - -//require the Twilio module and create a REST client -var client = require('twilio')(accountSid, authToken); - -client.messages.create({ - to: "812555121", - from: "+2605551212", - body: "This is a test", -}, function(err, message) { - console.log(message.sid); -}); - -// https://github.com/twilio/twilio-node/blob/master/LICENSE -// The MIT License (MIT) -// Copyright (c) 2010 Stephen Walters -// Copyright (c) 2012 Twilio Inc. - -// 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. \ No newline at end of file diff --git a/books/beaglebone-cookbook/06iot/code/twilioSetup.sh b/books/beaglebone-cookbook/06iot/code/twilioSetup.sh deleted file mode 100755 index c9a03388..00000000 --- a/books/beaglebone-cookbook/06iot/code/twilioSetup.sh +++ /dev/null @@ -1,2 +0,0 @@ -export TWILIO_ACCOUNT_SID="AC407ab27aab63fa995dbc24c43a18d204" -export TWILIO_AUTH_TOKEN="71fe036081445dd693ed80c3ebf0f9b1" \ No newline at end of file diff --git a/books/beaglebone-cookbook/06iot/code/twilioTest.py b/books/beaglebone-cookbook/06iot/code/twilioTest.py deleted file mode 100755 index 356cb03b..00000000 --- a/books/beaglebone-cookbook/06iot/code/twilioTest.py +++ /dev/null @@ -1,20 +0,0 @@ -#!/usr/bin/env python -# Download the helper library from https://www.twilio.com/docs/python/install -import os -from twilio.rest import Client - - -# Find your Account SID and Auth Token at twilio.com/console -# and set the environment variables. See http://twil.io/secure -account_sid = os.environ['TWILIO_ACCOUNT_SID'] -auth_token = os.environ['TWILIO_AUTH_TOKEN'] -client = Client(account_sid, auth_token) - -message = client.messages \ - .create( - body="Join Earth's mightiest heroes. Like Kevin Bacon.", - from_='+18122333219', - to='+18122333219' - ) - -print(message.sid) diff --git a/books/beaglebone-cookbook/06iot/code/twitterInstall.sh b/books/beaglebone-cookbook/06iot/code/twitterInstall.sh deleted file mode 100644 index 6cb7b7c0..00000000 --- a/books/beaglebone-cookbook/06iot/code/twitterInstall.sh +++ /dev/null @@ -1,4 +0,0 @@ -npm install -g node-twitter -# Go to https://apps.twitter.com/ -# "Create New App" -# Copy API and TOKEN to twitterKeys.js \ No newline at end of file diff --git a/books/beaglebone-cookbook/06iot/code/twitterKeys.sh b/books/beaglebone-cookbook/06iot/code/twitterKeys.sh deleted file mode 100755 index 9e5e9db3..00000000 --- a/books/beaglebone-cookbook/06iot/code/twitterKeys.sh +++ /dev/null @@ -1,10 +0,0 @@ -# My Twitter keys -# From https://apps.twitter.com/app/5771872/keys -export API_KEY='RKH9Bi6QDo8LIUydJN5ubBH7r' -export API_SECRET_KEY='DwyL7V4Q7O5ochI0PNlDsd00tA2lcSnEaxQSavSW4Jy86GKoxd' -export TOKEN='48435578-W5fX8R7k93gbwptwpmnp5FgRbsG2Hos8M20iV6140' -export TOKEN_SECRET='SOFLoyuBBkEsdvBKXh4CLBfQTiO2OiNtx3FQqnjYsHlRM' -export BEARER_TOKEN='AAAAAAAAAAAAAAAAAAAAAGASWAAAAAAAx3tNEacg9qMqvGRJsmc5ivTuuO0%3Dyu1wzpaLMQDsTgGrh21jAacNRNsnEYKLIuePlJy4kX7DnBeHNj' - -# Client ID dmNxcDVPencxT2l3Ry12OWFSdEc6MTpjaQ -# Client Secret 16tjW8lITIMH0ETUcmCvT1bpUvebCzsWQF3yVLv329rjynRSvT \ No newline at end of file diff --git a/books/beaglebone-cookbook/06iot/code/twitterPushbutton.js b/books/beaglebone-cookbook/06iot/code/twitterPushbutton.js deleted file mode 100755 index e3fe0c37..00000000 --- a/books/beaglebone-cookbook/06iot/code/twitterPushbutton.js +++ /dev/null @@ -1,39 +0,0 @@ -#!/usr/bin/env node -// From: https://www.npmjs.org/package/node-twitter -// Tweets with attached image media (JPG, PNG or GIF) can be posted -// using the upload API endpoint. -var Twitter = require('node-twitter'); -var b = require('bonescript'); -var key = require('./twitterKeys'); -var gpio = "P9_42"; -var count = 0; - -b.pinMode(gpio, b.INPUT); -b.attachInterrupt(gpio, sendTweet, b.FALLING); - -var twitterRestClient = new Twitter.RestClient( - key.API_KEY, key.API_SECRET, - key.TOKEN, key.TOKEN_SECRET -); - -function sendTweet() { - console.log("Sending..."); - count++; - - twitterRestClient.statusesUpdate( - {'status': 'Posting tweet ' + count + ' via my BeagleBone Black', }, - function(error, result) { - if (error) { - console.log('Error: ' + - (error.code ? error.code + ' ' + error.message : error.message)); - } - - if (result) { - console.log(result); - } - } - ); -} - -// node-twitter is made available under terms of the BSD 3-Clause License. -// http://www.opensource.org/licenses/BSD-3-Clause \ No newline at end of file diff --git a/books/beaglebone-cookbook/06iot/code/twitterSearch.js b/books/beaglebone-cookbook/06iot/code/twitterSearch.js deleted file mode 100755 index bb1d3edc..00000000 --- a/books/beaglebone-cookbook/06iot/code/twitterSearch.js +++ /dev/null @@ -1,20 +0,0 @@ -#!/usr/bin/env node -// From: https://www.npmjs.org/package/node-twitter -// The Twitter Search API can be accessed using Twitter.SearchClient. The following -// code example shows how to search for tweets containing the keyword "node.js".var Twitter = require('node-twitter'); -var key = require('./twitterKeys'); - -var twitterSearchClient = new Twitter.SearchClient( - key.API_KEY, key.API_SECRET, - key.TOKEN, key.TOKEN_SECRET -); - -twitterSearchClient.search({'q': 'rosehulman'}, function(error, result) { - if (error) { - console.log('Error: ' + (error.code ? error.code + ' ' + error.message : error.message)); - } - - if (result) { - console.log(result); - } -}); \ No newline at end of file diff --git a/books/beaglebone-cookbook/06iot/code/twitterStream.js b/books/beaglebone-cookbook/06iot/code/twitterStream.js deleted file mode 100755 index 35e2068a..00000000 --- a/books/beaglebone-cookbook/06iot/code/twitterStream.js +++ /dev/null @@ -1,44 +0,0 @@ -#!/usr/bin/env node -// From: https://www.npmjs.org/package/node-twitter -// The Twitter Streaming API can be accessed using Twitter.StreamClient. -// The following code example shows how to catch all tweets containing keywords. -var Twitter = require('node-twitter'); -var b = require('bonescript'); -var key = require('./twitterKeys'); -var gpio = "P9_14"; -var count = 0; -var timeOn = 5000; // Turn LED off after this amount of time (in ms) - -b.pinMode(gpio, b.OUTPUT); - -b.digitalWrite(gpio, 1); // Toggle LED -setTimeout(ledOff, timeOn); - -var twitterStreamClient = new Twitter.StreamClient( - key.API_KEY, key.API_SECRET, - key.TOKEN, key.TOKEN_SECRET -); - -twitterStreamClient.on('close', function() { - console.log('Connection closed.'); -}); -twitterStreamClient.on('end', function() { - console.log('End of Line.'); -}); -twitterStreamClient.on('error', function(error) { - console.log('Error: ' + (error.code ? error.code + ' ' + error.message : error.message)); -}); -twitterStreamClient.on('tweet', function(tweet) { - console.log(tweet); - b.digitalWrite(gpio, 1); // Turn LED on - console.log(count++ + " =====\ - tweet\ - ====="); - setTimeout(ledOff, timeOn); -}); - -twitterStreamClient.start(['beagleboard', 'beaglebone', 'cookbook', 'rosehulman']); - -function ledOff() { - b.digitalWrite(gpio, 0); -} \ No newline at end of file diff --git a/books/beaglebone-cookbook/06iot/code/twitterTimeLine.js b/books/beaglebone-cookbook/06iot/code/twitterTimeLine.js deleted file mode 100755 index dca85d32..00000000 --- a/books/beaglebone-cookbook/06iot/code/twitterTimeLine.js +++ /dev/null @@ -1,25 +0,0 @@ -#!/usr/bin/env node -// From: https://www.npmjs.org/package/node-twitter -// The Twitter REST API can be accessed using Twitter.RestClient. The following -// code example shows how to retrieve tweets from the authenticated user's timeline. -var Twitter = require('node-twitter'); -var key = require('./twitterKeys'); - -var twitterRestClient = new Twitter.RestClient( - key.API_KEY, key.API_SECRET, - key.TOKEN, key.TOKEN_SECRET -); - -twitterRestClient.statusesHomeTimeline({}, function(error, result) { - if (error) { - console.log('Error: ' + - (error.code ? error.code + ' ' + error.message : error.message)); - } - - if (result) { - console.log(result); - } -}); - -// node-twitter is made available under terms of the BSD 3-Clause License. -// http://www.opensource.org/licenses/BSD-3-Clause \ No newline at end of file diff --git a/books/beaglebone-cookbook/06iot/code/twitterUpload.js b/books/beaglebone-cookbook/06iot/code/twitterUpload.js deleted file mode 100755 index e09a900a..00000000 --- a/books/beaglebone-cookbook/06iot/code/twitterUpload.js +++ /dev/null @@ -1,32 +0,0 @@ -#!/usr/bin/env node -// From: https://www.npmjs.org/package/node-twitter -// Tweets with attached image media (JPG, PNG or GIF) can be posted -// using the upload API endpoint. -var Twitter = require('node-twitter'); -var b = require('bonescript'); -var key = require('./twitterKeys'); - -var twitterRestClient = new Twitter.RestClient( - key.API_KEY, key.API_SECRET, - key.TOKEN, key.TOKEN_SECRET -); - -twitterRestClient.statusesUpdateWithMedia( - { - 'status': 'Posting a tweet w/ attached media.', - 'media[]': '/root/cookbook-atlas/images/cover.png' - }, - function(error, result) { - if (error) { - console.log('Error: ' + - (error.code ? error.code + ' ' + error.message : error.message)); - } - - if (result) { - console.log(result); - } - } -); - -// node-twitter is made available under terms of the BSD 3-Clause License. -// http://www.opensource.org/licenses/BSD-3-Clause \ No newline at end of file diff --git a/books/beaglebone-cookbook/06iot/code/twitter_create_tweet.py b/books/beaglebone-cookbook/06iot/code/twitter_create_tweet.py deleted file mode 100755 index fc7829bc..00000000 --- a/books/beaglebone-cookbook/06iot/code/twitter_create_tweet.py +++ /dev/null @@ -1,75 +0,0 @@ -#!/usr/bin/env python -# From: https://github.com/twitterdev/Twitter-API-v2-sample-code/blob/main/Manage-Tweets/create_tweet.py -from requests_oauthlib import OAuth1Session -import os -import json - -# In your terminal please set your environment variables by running the following lines of code. -# export 'API_KEY'='<your_consumer_key>' -# export 'API_SECRET_KEY'='<your_consumer_secret>' - -consumer_key = os.environ.get("API_KEY") -consumer_secret = os.environ.get("API_SECRET_KEY") - -# Be sure to add replace the text of the with the text you wish to Tweet. You can also add parameters to post polls, quote Tweets, Tweet with reply settings, and Tweet to Super Followers in addition to other features. -payload = {"text": "Hello world!"} - -# Get request token -request_token_url = "https://api.twitter.com/oauth/request_token?oauth_callback=oob&x_auth_access_type=write" -oauth = OAuth1Session(consumer_key, client_secret=consumer_secret) - -try: - fetch_response = oauth.fetch_request_token(request_token_url) -except ValueError: - print( - "There may have been an issue with the consumer_key or consumer_secret you entered." - ) - -resource_owner_key = fetch_response.get("oauth_token") -resource_owner_secret = fetch_response.get("oauth_token_secret") -print("Got OAuth token: %s" % resource_owner_key) - -# Get authorization -base_authorization_url = "https://api.twitter.com/oauth/authorize" -authorization_url = oauth.authorization_url(base_authorization_url) -print("Please go here and authorize: %s" % authorization_url) -verifier = input("Paste the PIN here: ") - -# Get the access token -access_token_url = "https://api.twitter.com/oauth/access_token" -oauth = OAuth1Session( - consumer_key, - client_secret=consumer_secret, - resource_owner_key=resource_owner_key, - resource_owner_secret=resource_owner_secret, - verifier=verifier, -) -oauth_tokens = oauth.fetch_access_token(access_token_url) - -access_token = oauth_tokens["oauth_token"] -access_token_secret = oauth_tokens["oauth_token_secret"] - -# Make the request -oauth = OAuth1Session( - consumer_key, - client_secret=consumer_secret, - resource_owner_key=access_token, - resource_owner_secret=access_token_secret, -) - -# Making the request -response = oauth.post( - "https://api.twitter.com/2/tweets", - json=payload, -) - -if response.status_code != 201: - raise Exception( - "Request returned an error: {} {}".format(response.status_code, response.text) - ) - -print("Response code: {}".format(response.status_code)) - -# Saving the response as JSON -json_response = response.json() -print(json.dumps(json_response, indent=4, sort_keys=True)) diff --git a/books/beaglebone-cookbook/06iot/code/twitter_delete_tweet.py b/books/beaglebone-cookbook/06iot/code/twitter_delete_tweet.py deleted file mode 100755 index d35a1192..00000000 --- a/books/beaglebone-cookbook/06iot/code/twitter_delete_tweet.py +++ /dev/null @@ -1,72 +0,0 @@ -#!/usr/bin/env python -# From: https://github.com/twitterdev/Twitter-API-v2-sample-code/blob/main/Manage-Tweets/delete_tweet.py -from requests_oauthlib import OAuth1Session -import os -import json - -# In your terminal please set your environment variables by running the following lines of code. -# export 'API_KEY'='<your_consumer_key>' -# export 'API_SECRET_KEY'='<your_consumer_secret>' - -consumer_key = os.environ.get("API_KEY") -consumer_secret = os.environ.get("API_SECRET_KEY") - -# Be sure to replace tweet-id-to-delete with the id of the Tweet you wish to delete. The authenticated user must own the list in order to delete -id = "1547963178700533760" - -# Get request token -request_token_url = "https://api.twitter.com/oauth/request_token?oauth_callback=oob&x_auth_access_type=write" -oauth = OAuth1Session(consumer_key, client_secret=consumer_secret) - -try: - fetch_response = oauth.fetch_request_token(request_token_url) -except ValueError: - print( - "There may have been an issue with the consumer_key or consumer_secret you entered." - ) - -resource_owner_key = fetch_response.get("oauth_token") -resource_owner_secret = fetch_response.get("oauth_token_secret") -print("Got OAuth token: %s" % resource_owner_key) - -# Get authorization -base_authorization_url = "https://api.twitter.com/oauth/authorize" -authorization_url = oauth.authorization_url(base_authorization_url) -print("Please go here and authorize: %s" % authorization_url) -verifier = input("Paste the PIN here: ") - -# Get the access token -access_token_url = "https://api.twitter.com/oauth/access_token" -oauth = OAuth1Session( - consumer_key, - client_secret=consumer_secret, - resource_owner_key=resource_owner_key, - resource_owner_secret=resource_owner_secret, - verifier=verifier, -) -oauth_tokens = oauth.fetch_access_token(access_token_url) - -access_token = oauth_tokens["oauth_token"] -access_token_secret = oauth_tokens["oauth_token_secret"] - -# Make the request -oauth = OAuth1Session( - consumer_key, - client_secret=consumer_secret, - resource_owner_key=access_token, - resource_owner_secret=access_token_secret, -) - -# Making the request -response = oauth.delete("https://api.twitter.com/2/tweets/{}".format(id)) - -if response.status_code != 200: - raise Exception( - "Request returned an error: {} {}".format(response.status_code, response.text) - ) - -print("Response code: {}".format(response.status_code)) - -# Saving the response as JSON -json_response = response.json() -print(json_response) diff --git a/books/beaglebone-cookbook/06iot/code/twitter_recent_search.py b/books/beaglebone-cookbook/06iot/code/twitter_recent_search.py deleted file mode 100755 index 05693857..00000000 --- a/books/beaglebone-cookbook/06iot/code/twitter_recent_search.py +++ /dev/null @@ -1,42 +0,0 @@ -#!/usr/bin/env python -# From: https://github.com/twitterdev/Twitter-API-v2-sample-code/blob/main/Recent-Search/recent_search.py -import requests -import os -import json - -# To set your environment variables in your terminal run the following line: -# export 'BEARER_TOKEN'='<your_bearer_token>' -bearer_token = os.environ.get("BEARER_TOKEN") - -search_url = "https://api.twitter.com/2/tweets/search/recent" - -# Optional params: start_time,end_time,since_id,until_id,max_results,next_token, -# expansions,tweet.fields,media.fields,poll.fields,place.fields,user.fields -query_params = {'query': '(from:MarkAYoder) OR #MarkAYoder','tweet.fields': 'author_id'} -# query_params = {'query': '(from:twitterdev -is:retweet) OR #twitterdev','tweet.fields': 'author_id'} - - -def bearer_oauth(r): - """ - Method required by bearer token authentication. - """ - - r.headers["Authorization"] = f"Bearer {bearer_token}" - r.headers["User-Agent"] = "v2RecentSearchPython" - return r - -def connect_to_endpoint(url, params): - response = requests.get(url, auth=bearer_oauth, params=params) - print(response.status_code) - if response.status_code != 200: - raise Exception(response.status_code, response.text) - return response.json() - - -def main(): - json_response = connect_to_endpoint(search_url, query_params) - print(json.dumps(json_response, indent=4, sort_keys=True)) - - -if __name__ == "__main__": - main() diff --git a/books/beaglebone-cookbook/06iot/code/twitter_user_tweets.py b/books/beaglebone-cookbook/06iot/code/twitter_user_tweets.py deleted file mode 100755 index 19dac531..00000000 --- a/books/beaglebone-cookbook/06iot/code/twitter_user_tweets.py +++ /dev/null @@ -1,60 +0,0 @@ -#!/usr/bin/env python -# From: https://github.com/twitterdev/Twitter-API-v2-sample-code/blob/main/User-Tweet-Timeline/user_tweets.py -import requests -import os -import json - -# To set your environment variables in your terminal run the following line: -# export 'BEARER_TOKEN'='<your_bearer_token>' -bearer_token = os.environ.get("BEARER_TOKEN") - -def create_url(): - # Replace with user ID below - user_id = 48435578 - # return "https://api.twitter.com/2/users/{}/followers".format(user_id) - return "https://api.twitter.com/2/users/{}/tweets".format(user_id) - - -def get_params(): - # Tweet fields are adjustable. - # Options include: - # attachments, author_id, context_annotations, - # conversation_id, created_at, entities, geo, id, - # in_reply_to_user_id, lang, non_ai_64_lic_metrics, organic_metrics, - # possibly_sensitive, promoted_metrics, public_metrics, referenced_tweets, - # source, text, and withheld - return {"tweet.fields": "created_at"} - # return {} - - -def bearer_oauth(r): - """ - Method required by bearer token authentication. - """ - - r.headers["Authorization"] = f"Bearer {bearer_token}" - r.headers["User-Agent"] = "v2UserTweetsPython" - return r - - -def connect_to_endpoint(url, params): - response = requests.request("GET", url, auth=bearer_oauth, params=params) - print(response.status_code) - if response.status_code != 200: - raise Exception( - "Request returned an error: {} {}".format( - response.status_code, response.text - ) - ) - return response.json() - - -def main(): - url = create_url() - params = get_params() - json_response = connect_to_endpoint(url, params) - print(json.dumps(json_response, indent=4, sort_keys=True)) - - -if __name__ == "__main__": - main() diff --git a/books/beaglebone-cookbook/06iot/code/weather.py b/books/beaglebone-cookbook/06iot/code/weather.py deleted file mode 100755 index 1b165eb3..00000000 --- a/books/beaglebone-cookbook/06iot/code/weather.py +++ /dev/null @@ -1,46 +0,0 @@ -#!/usr/bin/env python3 -# Displays current weather and forcast -import os -import sys -from datetime import datetime -import requests # For getting weather - -# http://api.openweathermap.org/data/2.5/onecall -params = { - 'appid': os.environ['APPID'], - # 'city': 'brazil,indiana', - 'exclude': "minutely,hourly", - 'lat': '39.52', - 'lon': '-87.12', - 'units': 'imperial' - } -urlWeather = "http://api.openweathermap.org/data/2.5/onecall" - -print("Getting weather") - -try: - r = requests.get(urlWeather, params=params) - if(r.status_code==200): - # print("headers: ", r.headers) - # print("text: ", r.text) - # print("json: ", r.json()) - weather = r.json() - print("Temp: ", weather['current']['temp']) # <1> - print("Humid:", weather['current']['humidity']) - print("Low: ", weather['daily'][1]['temp']['min']) - print("High: ", weather['daily'][0]['temp']['max']) - day = weather['daily'][0]['sunrise']-weather['timezone_offset'] - print("sunrise: " + datetime.utcfromtimestamp(day).strftime('%Y-%m-%d %H:%M:%S')) - # print("Day: " + datetime.utcfromtimestamp(day).strftime('%a')) - # print("weather: ", weather['daily'][1]) # <2> - # print("weather: ", weather) # <3> - # print("icon: ", weather['current']['weather'][0]['icon']) - # print() - - else: - print("status_code: ", r.status_code) -except IOError: - print("File not found: " + tmp101) - print("Have you run setup.sh?") -except: - print("Unexpected error:", sys.exc_info()) diff --git a/books/beaglebone-cookbook/06iot/code/weatherSetup.sh b/books/beaglebone-cookbook/06iot/code/weatherSetup.sh deleted file mode 100755 index e2840d08..00000000 --- a/books/beaglebone-cookbook/06iot/code/weatherSetup.sh +++ /dev/null @@ -1,2 +0,0 @@ -# From:https://home.openweathermap.org/api_keys -export APPID="6a2db5c8171494bce131dc69af6f34b9" \ No newline at end of file diff --git a/books/beaglebone-cookbook/06iot/code/xbee.js b/books/beaglebone-cookbook/06iot/code/xbee.js deleted file mode 100644 index 40b184d2..00000000 --- a/books/beaglebone-cookbook/06iot/code/xbee.js +++ /dev/null @@ -1,2 +0,0 @@ -#!/usr/bin/env node -// This isn't working yet \ No newline at end of file diff --git a/books/beaglebone-cookbook/06iot/iot.rst b/books/beaglebone-cookbook/06iot/iot.rst index 4886a0e8..42768262 100644 --- a/books/beaglebone-cookbook/06iot/iot.rst +++ b/books/beaglebone-cookbook/06iot/iot.rst @@ -95,11 +95,11 @@ to a file called */var/www/html/test.html*, and then point your browser to *192. .. _networking_index_html: -.. literalinclude:: code/test.html +.. literalinclude:: ../code/06iot/test.html :caption: A sample web page (test.html) :linenos: -:download:`test.html <code/test.html>` +:download:`test.html <../code/06iot/test.html>` You will see the web page shown in :ref:`networking_node_page`. @@ -142,8 +142,8 @@ All the code in is the Cookbook repo: .. code-block:: bash - bone$ git clone https://github.com/MarkAYoder/BoneCookbook - bone$ cd BoneCookbook/doc/06iod/code/flash + bone$ git clone https://git.beagleboard.org/beagleboard/beaglebone-cookbook-code + bone$ cd beaglebone-cookbook-code/06iot/flask First Flask - hello, world ============================ @@ -152,11 +152,11 @@ Our first example is *helloWorld.py* .. _flask_hello_world: -.. literalinclude:: code/flask/helloWorld.py +.. literalinclude:: ../code/06iot/flask/helloWorld.py :caption: Python code for flask hello world (helloWorld.py) :linenos: -:download:`helloWorld.py <code/flask/helloWorld.py>` +:download:`helloWorld.py <../code/06iot/flask/helloWorld.py>` 1. The first line loads the Flask module into your Python script. @@ -188,11 +188,11 @@ Here's what's in *templates/index1.html*: .. _flask_index1: -.. literalinclude:: code/flask/templates/index1.html +.. literalinclude:: ../code/06iot/flask/templates/index1.html :caption: index1.html :linenos: -:download:`index1.html <code/flask/templates/index1.html>` +:download:`index1.html <../code/06iot/flask/templates/index1.html>` Note: a style sheet (style.css) is also included. This will be populated later. @@ -203,11 +203,11 @@ function. Now, let’s create a new Python script. We will name it app1.py: .. _flask_app1: -.. literalinclude:: code/flask/app1.py +.. literalinclude:: ../code/06iot/flask/app1.py :caption: app1.py :linenos: -:download:`app1.py <code/flask/app1.py>` +:download:`app1.py <../code/06iot/flask/app1.py>` Note that we create a formatted string("timeString") using the date and time from the "now" object, that has the current time stored on it. @@ -260,11 +260,11 @@ Let’s use a new Python script named *app2.py*. .. _flask_app2: -.. literalinclude:: code/flask/app2.py +.. literalinclude:: ../code/06iot/flask/app2.py :caption: A simple Flask-based web server to read a GPIO (app2.py) :linenos: -:download:`app2.py <code/flask/app2.py>` +:download:`app2.py <../code/06iot/flask/app2.py>` Look that what we are doing is defining the button on *P9_11* as input, reading its value and storing it in *buttonSts*. Inside the function *index()*, we will pass that value to our web @@ -274,11 +274,11 @@ Let’s also see the new *index2.html* to show the GPIO status: .. _flask_index2: -.. literalinclude:: code/flask/templates/index2.html +.. literalinclude:: ../code/06iot/flask/templates/index2.html :caption: A simple Flask-based web server to read a GPIO (index2.html) :linenos: -:download:`index2.html <code/flask/templates/index2.html>` +:download:`index2.html <../code/06iot/flask/templates/index2.html>` Now, run the following command: @@ -326,7 +326,7 @@ A simple Flask-based web server to read a GPIO (app3.py) .. code-block:: python - include::code/flask/app3.py + include::../code/06iot/flask/app3.py @@ -359,11 +359,11 @@ actuator and more important, create “buttons†to send the commands: .. _flask_index3: -.. literalinclude:: code/flask/templates/index3.html +.. literalinclude:: ../code/06iot/flask/templates/index3.html :caption: A simple Flask-based web server to write a GPIO (index3.html) :linenos: -:download:`index3.html <code/flask/templates/index3.html>` +:download:`index3.html <../code/06iot/flask/templates/index3.html>` .. code-block:: bash @@ -457,11 +457,11 @@ plot the buffer is here: analogInContinuous.py .. _analog_code: -.. literalinclude:: code/analogInContinuous.py +.. literalinclude:: ../code/06iot/analogInContinuous.py :caption: Code to read and plot a continuous analog input(analogInContinuous.py) :linenos: -:download:`analogInContinuous.py <code/analogInContinuous.py>` +:download:`analogInContinuous.py <../code/06iot/analogInContinuous.py>` Be sure to read the instillation instructions in the comments. Also note this uses X windows and you need to *ssh -X 192.168.7.2* for X to know where the display is. @@ -472,7 +472,7 @@ Run it: host$ ssh -X bone - bone$ cd <Cookbook repo>/doc/06iot/code>/strong> + bone$ cd beaglebone-cookbook-code/06iot bone$ ./analogInContinuous.py Hit ^C to stop @@ -562,7 +562,7 @@ A number of files get installed, including the ADC file. Now try rerunning. .. code-block:: bash - bone$ cd <Cookbook repo>/docs/06iot/code> + bone$ cd beaglebone-cookbook-code/06iot bone$ ./analogInContinuous.py Hit ^C to stop @@ -609,11 +609,11 @@ Then add the code in :ref:`networking_nodemailer_code` to a file named ``emailTe .. _networking_nodemailer_code: -.. literalinclude:: code/emailTest.py +.. literalinclude:: ../code/06iot/emailTest.py :caption: Sending email using nodemailer (emailtTest.py) :linenos: -:download:`emailTest.py <code/emailTest.py>` +:download:`emailTest.py <../code/06iot/emailTest.py>` Then run the script to send the email: @@ -665,12 +665,12 @@ Finally, add the code in :ref:`networking_twilio_code` to a file named ``twilio- .. _networking_twilio_code: -.. literalinclude:: code/twilio-test.js +.. literalinclude:: ../code/06iot/twilio-test.js :caption: Sending SMS messages using Twilio (``twilio-test.js``) :linenos: -:download:`twilio-test.js <code/twilio-test.js>` -:download:`nodemailer-test.js <code/nodemailer-test.js>` +:download:`twilio-test.js <../code/06iot/twilio-test.js>` +:download:`nodemailer-test.js <../code/06iot/nodemailer-test.js>` Twilio allows a small number of free text messages, enough to test your code and to play around some. @@ -701,11 +701,11 @@ Because your Bone is on the network, it's not hard to access the current weather .. _networking_weather_code: -.. literalinclude:: code/weather.py +.. literalinclude:: ../code/06iot/weather.py :caption: Code for getting current weather conditions (``weather.py``) :linenos: -:download:`weather.py <code/weather.py>` +:download:`weather.py <../code/06iot/weather.py>` 1. Prints current conditions. 2. Prints the forecast for the next day. @@ -776,11 +776,11 @@ Add the code in :ref:`twitter_create_code` to a file called .. _twitter_create_code: -.. literalinclude:: code/twitter_create_tweet.py +.. literalinclude:: ../code/06iot/twitter_create_tweet.py :caption: Create a Tweet (``twitter_create_tweet.py``) :linenos: -:download:`twitter_create_tweet.py <code/twitter_create_tweet.py>` +:download:`twitter_create_tweet.py <../code/06iot/twitter_create_tweet.py>` Run the code and you'll have to authorize. @@ -809,11 +809,11 @@ Around line 15 is the *id* number. Paste in the value returned above. .. _twitter_delete_code: -.. literalinclude:: code/twitter_delete_tweet.py +.. literalinclude:: ../code/06iot/twitter_delete_tweet.py :caption: Code to delete a tweet (``twitter_delete_tweet.py``) :linenos: -:download:`twitter_delete_tweet.py <code/twitter_delete_tweet.py>` +:download:`twitter_delete_tweet.py <../code/06iot/twitter_delete_tweet.py>` .. TODO Start Here @@ -822,11 +822,11 @@ The code in :ref:`networking_pushbutton_code` snds a tweet whenever a button is .. _networking_pushbutton_code: -.. literalinclude:: code/twitterPushbutton.js +.. literalinclude:: ../code/06iot/twitterPushbutton.js :caption: Tweet when a button is pushed (twitterPushbutton.js) :linenos: -:download:`twitterPushbutton.js <code/twitterPushbutton.js>` +:download:`twitterPushbutton.js <../code/06iot/twitterPushbutton.js>` To see many other examples, go to `iStrategyLabs node-twitter GitHub page <http://bit.ly/18AvST>`_. @@ -1042,11 +1042,11 @@ to a file called ``launchPad.ino`` and run it on your LaunchPad. .. _js_launchPad_code: -.. literalinclude:: code/launchPad/launchPad.ino +.. literalinclude:: ../code/06iot/launchPad/launchPad.ino :caption: LaunchPad code for communicating via the UART (launchPad.ino) :linenos: -:download:`launchPad.ino <code/launchPad/launchPad.ino>` +:download:`launchPad.ino <../code/06iot/launchPad/launchPad.ino>` 1. Set the mode for the built-in red and green LEDs. @@ -1064,11 +1064,11 @@ On the Bone, add the script in :ref:`js_launchPadBeagle_code` to a file called ` .. _js_launchPadBeagle_code: -.. literalinclude:: code/launchPad.js +.. literalinclude:: ../code/06iot/launchPad.js :caption: Code for communicating via the UART (launchPad.js) :linenos: -:download:`launchPad.js <code/launchPad.js>` +:download:`launchPad.js <../code/06iot/launchPad.js>` 1. Select which serial port to use. :ref:`networking_cape-headers-serial_fig` sows what's available. We've wired *P9_24* and *P9_26*, so we are using serial port */dev/ttyO1*. (Note that's the letter ``O`` and not the number ``zero``.) diff --git a/books/beaglebone-cookbook/07kernel/code/Makefile b/books/beaglebone-cookbook/07kernel/code/Makefile deleted file mode 100644 index c151dc6d..00000000 --- a/books/beaglebone-cookbook/07kernel/code/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -obj-m := hello.o -KDIR := /lib/modules/$(shell uname -r)/build - -all: - make -C $(KDIR) M=$$PWD - -clean: - rm hello.mod.c hello.o modules.order hello.mod.o Module.symvers diff --git a/books/beaglebone-cookbook/07kernel/code/Makefile.display b/books/beaglebone-cookbook/07kernel/code/Makefile.display deleted file mode 100644 index a7f5a1fc..00000000 --- a/books/beaglebone-cookbook/07kernel/code/Makefile.display +++ /dev/null @@ -1,8 +0,0 @@ -obj-m := hello.o -KDIR := /lib/modules/$(shell uname -r)/build - -all: -<TAB>make -C $(KDIR) M=$$PWD - -clean: -<TAB>rm hello.mod.c hello.o modules.order hello.mod.o Module.symvers diff --git a/books/beaglebone-cookbook/07kernel/code/hello.c b/books/beaglebone-cookbook/07kernel/code/hello.c deleted file mode 100644 index b3392a72..00000000 --- a/books/beaglebone-cookbook/07kernel/code/hello.c +++ /dev/null @@ -1,22 +0,0 @@ -#include <linux/module.h> /* Needed by all modules */ -#include <linux/kernel.h> /* Needed for KERN_INFO */ -#include <linux/init.h> /* Needed for the macros */ - -static int __init hello_start(void) -{ - printk(KERN_INFO "Loading hello module...\n"); - printk(KERN_INFO "Hello, World!\n"); - return 0; -} - -static void __exit hello_end(void) -{ - printk(KERN_INFO "Goodbye Boris\n"); -} - -module_init(hello_start); -module_exit(hello_end); - -MODULE_AUTHOR("Boris Houndleroy"); -MODULE_DESCRIPTION("Hello World Example"); -MODULE_LICENSE("GPL"); diff --git a/books/beaglebone-cookbook/07kernel/code/hello.patch b/books/beaglebone-cookbook/07kernel/code/hello.patch deleted file mode 100644 index deb5c615..00000000 --- a/books/beaglebone-cookbook/07kernel/code/hello.patch +++ /dev/null @@ -1,53 +0,0 @@ -From eaf4f7ea7d540bc8bb57283a8f68321ddb4401f4 Mon Sep 17 00:00:00 2001 -From: Jason Kridner <jdk@ti.com> -Date: Tue, 12 Feb 2013 02:18:03 +0000 -Subject: [PATCH] hello: example kernel modules - ---- - hello/Makefile | 7 +++++++ - hello/hello.c | 18 ++++++++++++++++++ - 2 files changed, 25 insertions(+), 0 deletions(-) - create mode 100644 hello/Makefile - create mode 100644 hello/hello.c - -diff --git a/hello/Makefile b/hello/Makefile -new file mode 100644 -index 0000000..4b23da7 ---- /dev/null -+++ b/hello/Makefile -@@ -0,0 +1,7 @@ -+obj-m := hello.o -+ -+PWD := $(shell pwd) -+KDIR := ${PWD}/.. -+ -+default: -+ make -C $(KDIR) SUBDIRS=$(PWD) modules -diff --git a/hello/hello.c b/hello/hello.c -new file mode 100644 -index 0000000..157d490 ---- /dev/null -+++ b/hello/hello.c -@@ -0,0 +1,22 @@ -+#include <linux/module.h> /* Needed by all modules */ -+#include <linux/kernel.h> /* Needed for KERN_INFO */ -+#include <linux/init.h> /* Needed for the macros */ -+ -+static int __init hello_start(void) -+{ -+ printk(KERN_INFO "Loading hello module...\n"); -+ printk(KERN_INFO "Hello, World!\n"); -+ return 0; -+} -+ -+static void __exit hello_end(void) -+{ -+ printk(KERN_INFO "Goodbye Boris\n"); -+} -+ -+module_init(hello_start); -+module_exit(hello_end); -+ -+MODULE_AUTHOR("Boris Houndleroy"); -+MODULE_DESCRIPTION("Hello World Example"); -+MODULE_LICENSE("GPL"); diff --git a/books/beaglebone-cookbook/07kernel/code/helloWorld.c b/books/beaglebone-cookbook/07kernel/code/helloWorld.c deleted file mode 100644 index 0fd542de..00000000 --- a/books/beaglebone-cookbook/07kernel/code/helloWorld.c +++ /dev/null @@ -1,5 +0,0 @@ -#include <stdio.h> - -int main(int argc, char **argv) { - printf("Hello, World! \n"); -} diff --git a/books/beaglebone-cookbook/07kernel/kernel.rst b/books/beaglebone-cookbook/07kernel/kernel.rst index c18a91ef..b57809bb 100644 --- a/books/beaglebone-cookbook/07kernel/kernel.rst +++ b/books/beaglebone-cookbook/07kernel/kernel.rst @@ -94,11 +94,11 @@ For our example module, add the code in :ref:`kernel_simple_module` to a file ca .. _kernel_simple_module: -.. literalinclude:: code/hello.c +.. literalinclude:: ../code/07kernel/hello.c :caption: Simple Kernel Module (hello.c) :linenos: -:download:`hello.c <code/hello.c>` +:download:`hello.c <../code/07kernel/hello.c>` When compiling on the Bone, all you need to do is load the Kernel Headers for the version of the kernel you're running: @@ -120,11 +120,11 @@ Next, add the code in :ref:`kernel_Makefle` to a file called ``Makefile``. .. _kernel_Makefle: -.. literalinclude:: code/Makefile.display +.. literalinclude:: ../code/07kernel/Makefile.display :caption: Simple Kernel Module (``Makefile``) :linenos: -:download:`Makefile.display <code/Makefile.display>` +:download:`Makefile.display <../code/07kernel/Makefile.display>` .. note:: Replace the two instances of *<TAB>* with a tab character (the key left of the Q key on a United States keyboard). @@ -137,13 +137,13 @@ Now, compile the kernel module by using the *make* command: bone$ make make -C /lib/modules/3.8.13-bone67/build \ - SUBDIRS=/root/cookbook-atlas/code/hello modules + SUBDIRS=/home/debian/beaglebone-cookbook-code/07kernel/hello modules make[1]: Entering directory `/usr/src/linux-headers-3.8.13-bone67' - CC [M] /root/cookbook-atlas/code/hello/hello.o + CC [M] /home/debian/beaglebone-cookbook-code/07kernel/hello/hello.o Building modules, stage 2. MODPOST 1 modules - CC /root/cookbook-atlas/code/hello/hello.mod.o - LD [M] /root/cookbook-atlas/code/hello/hello.ko + CC /home/debian/beaglebone-cookbook-code/07kernel/hello/hello.mod.o + LD [M] /home/debian/beaglebone-cookbook-code/07kernel/hello/hello.ko make[1]: Leaving directory `/usr/src/linux-headers-3.8.13-bone67' bone$ ls Makefile hello.c hello.mod.c hello.o @@ -156,7 +156,7 @@ Notice that several files have been created. .. code-block:: bash bone$ modinfo hello.ko - filename: /root/hello/hello.ko + filename: /home/debian/beaglebone-cookbook-code/07kernel/hello/hello.ko srcversion: 87C6AEED7791B4B90C3B50C depends: vermagic: 3.8.13-bone67 SMP mod_unload modversions ARMv7 thumb2 p2v8 @@ -581,11 +581,11 @@ tools to use. Test the cross compiler by adding :ref:`kernel_helloWorld` to a fi .. _kernel_helloWorld: -.. literalinclude:: code/helloWorld.c +.. literalinclude:: ../code/07kernel/helloWorld.c :caption: Simple helloWorld.c to test cross compiling (helloWorld.c) :linenos: -:download:`helloWorld.c <code/helloWorld.c>` +:download:`helloWorld.c <../code/07kernel/helloWorld.c>` You can then cross-compile by using the following commands: @@ -617,11 +617,11 @@ Solution .. _kernel_hello_patch: -.. literalinclude:: code/hello.patch +.. literalinclude:: ../code/07kernel/hello.patch :caption: Simple kernel patch file (hello.patch) :linenos: -:download:`hello.patch <code/hello.patch>` +:download:`hello.patch <../code/07kernel/hello.patch>` Here's how to use it: diff --git a/books/beaglebone-cookbook/08realtime/code/pushLED.c b/books/beaglebone-cookbook/08realtime/code/pushLED.c deleted file mode 100755 index 118210df..00000000 --- a/books/beaglebone-cookbook/08realtime/code/pushLED.c +++ /dev/null @@ -1,68 +0,0 @@ -//////////////////////////////////////// -// blinkLED.c -// Blinks the P9_14 pin based on the P9_42 pin -// Wiring: -// Setup: -// See: -//////////////////////////////////////// -#include <stdio.h> -#include <string.h> -#include <unistd.h> -#define MAXSTR 100 - -int main() { - FILE *fpbutton, *fpLED; - char LED[] = "50"; // Look up P9.14 using gpioinfo | grep -e chip -e P9.14. chip 1, line 18 maps to 50 - char button[] = "7"; // Look up P9.42 using gpioinfo | grep -e chip -e P9.42. chip 0, line 7 maps to 7 - char GPIOPATH[] = "/sys/class/gpio"; - char path[MAXSTR] = ""; - - // Make sure LED is exported - snprintf(path, MAXSTR, "%s%s%s", GPIOPATH, "/gpio", LED); - if (!access(path, F_OK) == 0) { - snprintf(path, MAXSTR, "%s%s", GPIOPATH, "/export"); - fpLED = fopen(path, "w"); - fprintf(fpLED, "%s", LED); - fclose(fpLED); - } - - // Make it an output LED - snprintf(path, MAXSTR, "%s%s%s%s", GPIOPATH, "/gpio", LED, "/direction"); - fpLED = fopen(path, "w"); - fprintf(fpLED, "out"); - fclose(fpLED); - - // Make sure bbuttonutton is exported - snprintf(path, MAXSTR, "%s%s%s", GPIOPATH, "/gpio", button); - if (!access(path, F_OK) == 0) { - snprintf(path, MAXSTR, "%s%s", GPIOPATH, "/export"); - fpbutton = fopen(path, "w"); - fprintf(fpbutton, "%s", button); - fclose(fpbutton); - } - - // Make it an input button - snprintf(path, MAXSTR, "%s%s%s%s", GPIOPATH, "/gpio", button, "/direction"); - fpbutton = fopen(path, "w"); - fprintf(fpbutton, "in"); - fclose(fpbutton); - - // I don't know why I can open the LED outside the loop and use fseek before - // each read, but I can't do the same for the button. It appears it needs - // to be opened every time. - snprintf(path, MAXSTR, "%s%s%s%s", GPIOPATH, "/gpio", LED, "/value"); - fpLED = fopen(path, "w"); - - char state = '0'; - - while (1) { - snprintf(path, MAXSTR, "%s%s%s%s", GPIOPATH, "/gpio", button, "/value"); - fpbutton = fopen(path, "r"); - fseek(fpLED, 0L, SEEK_SET); - fscanf(fpbutton, "%c", &state); - printf("state: %c\n", state); - fprintf(fpLED, "%c", state); - fclose(fpbutton); - usleep(250000); // sleep time in microseconds - } -} \ No newline at end of file diff --git a/books/beaglebone-cookbook/08realtime/code/pushLED.js b/books/beaglebone-cookbook/08realtime/code/pushLED.js deleted file mode 100755 index 485a2bbf..00000000 --- a/books/beaglebone-cookbook/08realtime/code/pushLED.js +++ /dev/null @@ -1,39 +0,0 @@ -#!/usr/bin/env node -//////////////////////////////////////// -// pushLED.js -// Blinks an LED attached to P9_12 when the button at P9_42 is pressed -// Wiring: -// Setup: -// See: -//////////////////////////////////////// -const fs = require("fs"); - -const ms = 500 // Read time in ms - -const LED="50"; // Look up P9.14 using gpioinfo | grep -e chip -e P9.14. chip 1, line 18 maps to 50 -const button="7"; // P9_42 mapps to 7 - -GPIOPATH="/sys/class/gpio/"; - -// Make sure LED is exported -if(!fs.existsSync(GPIOPATH+"gpio"+LED)) { - fs.writeFileSync(GPIOPATH+"export", LED); -} -// Make it an output pin -fs.writeFileSync(GPIOPATH+"gpio"+LED+"/direction", "out"); - -// Make sure button is exported -if(!fs.existsSync(GPIOPATH+"gpio"+button)) { - fs.writeFileSync(GPIOPATH+"export", button); -} -// Make it an input pin -fs.writeFileSync(GPIOPATH+"gpio"+button+"/direction", "in"); - -// Read every ms -setInterval(flashLED, ms); - -function flashLED() { - var data = fs.readFileSync(GPIOPATH+"gpio"+button+"/value").slice(0, -1); - console.log('data = ' + data); - fs.writeFileSync(GPIOPATH+"gpio"+LED+"/value", data); - } diff --git a/books/beaglebone-cookbook/08realtime/code/pushLED.py b/books/beaglebone-cookbook/08realtime/code/pushLED.py deleted file mode 100755 index 7606e090..00000000 --- a/books/beaglebone-cookbook/08realtime/code/pushLED.py +++ /dev/null @@ -1,49 +0,0 @@ -#!/usr/bin/env python -# //////////////////////////////////////// -# // pushLED.py -# // Blinks an LED attached to P9_12 when the button at P9_42 is pressed -# // Wiring: -# // Setup: -# // See: -# //////////////////////////////////////// -import time -import os - -ms = 50 # Read time in ms - -LED="50" # Look up P9.14 using gpioinfo | grep -e chip -e P9.14. chip 1, line 18 maps to 50 -button="7" # P9_42 mapps to 7 - -GPIOPATH="/sys/class/gpio/" - -# Make sure LED is exported -if (not os.path.exists(GPIOPATH+"gpio"+LED)): - f = open(GPIOPATH+"export", "w") - f.write(LED) - f.close() - -# Make it an output pin -f = open(GPIOPATH+"gpio"+LED+"/direction", "w") -f.write("out") -f.close() - -# Make sure button is exported -if (not os.path.exists(GPIOPATH+"gpio"+button)): - f = open(GPIOPATH+"export", "w") - f.write(button) - f.close() - -# Make it an output pin -f = open(GPIOPATH+"gpio"+button+"/direction", "w") -f.write("in") -f.close() - -# Read every ms -fin = open(GPIOPATH+"gpio"+button+"/value", "r") -fout = open(GPIOPATH+"gpio"+LED+"/value", "w") - -while True: - fin.seek(0) - fout.seek(0) - fout.write(fin.read()) - time.sleep(ms/1000) diff --git a/books/beaglebone-cookbook/08realtime/code/pushLEDmmap.c b/books/beaglebone-cookbook/08realtime/code/pushLEDmmap.c deleted file mode 100644 index 35f82668..00000000 --- a/books/beaglebone-cookbook/08realtime/code/pushLEDmmap.c +++ /dev/null @@ -1,68 +0,0 @@ -// From: http://stackoverflow.com/questions/13124271/driving-beaglebone-gpio -// -through-dev-mem -// user contributions licensed under cc by-sa 3.0 with attribution required -// http://creativecommons.org/licenses/by-sa/3.0/ -// http://blog.stackoverflow.com/2009/06/attribution-required/ -// Author: madscientist159 (http://stackoverflow.com/users/3000377/madscientist159) -// -// Read one gpio pin and write it out to another using mmap. -// Be sure to set -O3 when compiling. -#include <stdio.h> -#include <stdlib.h> -#include <sys/mman.h> -#include <fcntl.h> -#include <signal.h> // Defines signal-handling functions (i.e. trap Ctrl-C) -#include "pushLEDmmap.h" - -// Global variables -int keepgoing = 1; // Set to 0 when Ctrl-c is pressed - -// Callback called when SIGINT is sent to the process (Ctrl-C) -void signal_handler(int sig) { - printf( "\nCtrl-C pressed, cleaning up and exiting...\n" ); - keepgoing = 0; -} - -int main(int argc, char *argv[]) { - volatile void *gpio_addr; - volatile unsigned int *gpio_datain; - volatile unsigned int *gpio_setdataout_addr; - volatile unsigned int *gpio_cleardataout_addr; - - // Set the signal callback for Ctrl-C - signal(SIGINT, signal_handler); - - int fd = open("/dev/mem", O_RDWR); - - printf("Mapping %X - %X (size: %X)\n", GPIO0_START_ADDR, GPIO0_END_ADDR, - GPIO0_SIZE); - - gpio_addr = mmap(0, GPIO0_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, - GPIO0_START_ADDR); - - gpio_datain = gpio_addr + GPIO_DATAIN; - gpio_setdataout_addr = gpio_addr + GPIO_SETDATAOUT; - gpio_cleardataout_addr = gpio_addr + GPIO_CLEARDATAOUT; - - if(gpio_addr == MAP_FAILED) { - printf("Unable to map GPIO\n"); - exit(1); - } - printf("GPIO mapped to %p\n", gpio_addr); - printf("GPIO SETDATAOUTADDR mapped to %p\n", gpio_setdataout_addr); - printf("GPIO CLEARDATAOUT mapped to %p\n", gpio_cleardataout_addr); - - printf("Start copying GPIO_07 to GPIO_31\n"); - while(keepgoing) { - if(*gpio_datain & GPIO_07) { - *gpio_setdataout_addr= GPIO_31; - } else { - *gpio_cleardataout_addr = GPIO_31; - } - //usleep(1); - } - - munmap((void *)gpio_addr, GPIO0_SIZE); - close(fd); - return 0; -} diff --git a/books/beaglebone-cookbook/08realtime/code/pushLEDmmap.h b/books/beaglebone-cookbook/08realtime/code/pushLEDmmap.h deleted file mode 100644 index a9b49331..00000000 --- a/books/beaglebone-cookbook/08realtime/code/pushLEDmmap.h +++ /dev/null @@ -1,35 +0,0 @@ -// From: http://stackoverflow.com/questions/13124271/driving-beaglebone-gpio -// -through-dev-mem -// user contributions licensed under cc by-sa 3.0 with attribution required -// http://creativecommons.org/licenses/by-sa/3.0/ -// http://blog.stackoverflow.com/2009/06/attribution-required/ -// Author: madscientist159 (http://stackoverflow.com/users/3000377/madscientist159) - -#ifndef _BEAGLEBONE_GPIO_H_ -#define _BEAGLEBONE_GPIO_H_ - -#define GPIO0_START_ADDR 0x44e07000 -#define GPIO0_END_ADDR 0x44e08000 -#define GPIO0_SIZE (GPIO0_END_ADDR - GPIO0_START_ADDR) - -#define GPIO1_START_ADDR 0x4804C000 -#define GPIO1_END_ADDR 0x4804D000 -#define GPIO1_SIZE (GPIO1_END_ADDR - GPIO1_START_ADDR) - -#define GPIO2_START_ADDR 0x41A4C000 -#define GPIO2_END_ADDR 0x41A4D000 -#define GPIO2_SIZE (GPIO2_END_ADDR - GPIO2_START_ADDR) - -#define GPIO3_START_ADDR 0x41A4E000 -#define GPIO3_END_ADDR 0x41A4F000 -#define GPIO3_SIZE (GPIO3_END_ADDR - GPIO3_START_ADDR) - -#define GPIO_DATAIN 0x138 -#define GPIO_SETDATAOUT 0x194 -#define GPIO_CLEARDATAOUT 0x190 - -#define GPIO_03 (1<<3) -#define GPIO_07 (1<<7) -#define GPIO_31 (1<<31) -#define GPIO_60 (1<<28) -#endif \ No newline at end of file diff --git a/books/beaglebone-cookbook/08realtime/code/rt/cyclictest.png b/books/beaglebone-cookbook/08realtime/code/rt/cyclictest.png deleted file mode 100644 index 1e6780c155c297043268bda39a18e8acf77fbda2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6556 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 Qowc@+fwBH`UAu_?0;qpzX#fBK diff --git a/books/beaglebone-cookbook/08realtime/code/rt/hist.gen b/books/beaglebone-cookbook/08realtime/code/rt/hist.gen deleted file mode 100755 index e265fc7f..00000000 --- a/books/beaglebone-cookbook/08realtime/code/rt/hist.gen +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/sh -# This code is from Julia Cartwright julia@kernel.org - -cyclictest -m -S -p 90 -h 400 -l "${1:-100000}" diff --git a/books/beaglebone-cookbook/08realtime/code/rt/hist.plt b/books/beaglebone-cookbook/08realtime/code/rt/hist.plt deleted file mode 100755 index 26d130b1..00000000 --- a/books/beaglebone-cookbook/08realtime/code/rt/hist.plt +++ /dev/null @@ -1,17 +0,0 @@ -# This code is from Julia Cartwright julia@kernel.org - -set terminal png medium size 800,600 -# set terminal X11 persist -set output "cyclictest.png" -set datafile commentschars "#" - -set logscale y - -# trim some of the distortion from the bottom of the plot -set yrang [0.85:*] - -set xlabel "t (us)" -set ylabel "Count" - -plot "nort.hist" using 1:2 with histeps title "NON-RT", \ - "rt.hist" using 1:2 with histeps title "PREEMPT-RT" diff --git a/books/beaglebone-cookbook/08realtime/code/rt/install.sh b/books/beaglebone-cookbook/08realtime/code/rt/install.sh deleted file mode 100755 index 7240ba2c..00000000 --- a/books/beaglebone-cookbook/08realtime/code/rt/install.sh +++ /dev/null @@ -1,3 +0,0 @@ -sudo apt install rt-tests -# You can run gnuplot on the host -sudo apt install gnuplot diff --git a/books/beaglebone-cookbook/08realtime/code/rt/setup.sh b/books/beaglebone-cookbook/08realtime/code/rt/setup.sh deleted file mode 100755 index c8003f2c..00000000 --- a/books/beaglebone-cookbook/08realtime/code/rt/setup.sh +++ /dev/null @@ -1,3 +0,0 @@ -# This may be needed to run rt -echo 950000 | sudo tee /sys/fs/cgroup/cpu/cpu.rt_runtime_us -echo 950000 | sudo tee /sys/fs/cgroup/cpu/user.slice/cpu.rt_runtime_us diff --git a/books/beaglebone-cookbook/08realtime/realtime.rst b/books/beaglebone-cookbook/08realtime/realtime.rst index 79fe98b2..c306a7b4 100644 --- a/books/beaglebone-cookbook/08realtime/realtime.rst +++ b/books/beaglebone-cookbook/08realtime/realtime.rst @@ -62,19 +62,19 @@ pushbutton, and turns on the LED attached to *P9_12* when the button is pushed. .. _py_pushLED_code: -.. literalinclude:: code/pushLED.py +.. literalinclude:: ../code/08realtime/pushLED.py :caption: Monitoring a pushbutton (pushLED.py) :linenos: -:download:`pushLED.py <code/pushLED.py>` +:download:`pushLED.py <../code/08realtime/pushLED.py>` .. _realtime_pushLED_code: -.. literalinclude:: code/pushLED.js +.. literalinclude:: ../code/08realtime/pushLED.js :caption: Monitoring a pushbutton (pushLED.js) :linenos: -:download:`pushLED.js <code/pushLED.js>` +:download:`pushLED.js <../code/08realtime/pushLED.js>` Add the code to a file named ``pushLED.js`` and run it by using the following commands: @@ -112,11 +112,11 @@ Then add the code in :ref:`realtime_pushLED_c_code` to a file named ``pushLED.c` .. _realtime_pushLED_c_code: -.. literalinclude:: code/pushLED.c +.. literalinclude:: ../code/08realtime/pushLED.c :caption: Code for reading a switch and blinking an LED (pushLED.c) :linenos: -:download:`pushLED.c <code/pushLED.c>` +:download:`pushLED.c <../code/08realtime/pushLED.c>` Compile and run the code: @@ -280,22 +280,22 @@ Add the code in :ref:`realtime_pushLEDmmap_h` to a file named ``pushLEDmmap.h``. .. _realtime_pushLEDmmap_h: -.. literalinclude:: code/pushLEDmmap.h +.. literalinclude:: ../code/08realtime/pushLEDmmap.h :caption: Memory address definitions (pushLEDmmap.h) :linenos: -:download:`pushLEDmmap.h <code/pushLEDmmap.h>` +:download:`pushLEDmmap.h <../code/08realtime/pushLEDmmap.h>` Add the code in :ref:`realtime_pushLEDmmap_c` to a file named ``pushLEDmmap.c``. .. _realtime_pushLEDmmap_c: -.. literalinclude:: code/pushLEDmmap.c +.. literalinclude:: ../code/08realtime/pushLEDmmap.c :caption: Code for directly reading memory addresses (pushLEDmmap.c) :linenos: -:download:`pushLEDmmap.c <code/pushLEDmmap.c>` +:download:`pushLEDmmap.c <../code/08realtime/pushLEDmmap.c>` Now, compile and run the code: @@ -407,11 +407,11 @@ Here's how to run the scripts. .. _realtime_install_fig: -.. literalinclude:: code/rt/install.sh +.. literalinclude:: ../code/08realtime/rt/install.sh :caption: rt/install.sh :linenos: -:download:`rt/install.sh <code/rt/install.sh>` +:download:`rt/install.sh <../code/08realtime/rt/install.sh>` * Open up another window and start something that will create a load on the Bone, then run the following: @@ -425,11 +425,11 @@ The data is saved in *nort.hist*, which stands for no RT histogram. .. _realtime_hist_gen_fig: -.. literalinclude:: code/rt/hist.gen +.. literalinclude:: ../code/08realtime/rt/hist.gen :caption: hist.gen :linenos: -:download:`rt/hist.gen <code/rt/hist.gen>` +:download:`rt/hist.gen <../code/08realtime/rt/hist.gen>` .. note:: If you get an error: @@ -486,7 +486,7 @@ This will generate the file *cyclictest.png* which contains your plot. It shoul .. _realtime_cyclictest_fig: -.. figure:: code/rt/cyclictest.png +.. figure:: ../code/08realtime/rt/cyclictest.png :align: center :alt: Histogram of Non-RT and RT kernels running cyclictest diff --git a/books/beaglebone-cookbook/09capes/code/quickBot_motor_test.js b/books/beaglebone-cookbook/09capes/code/quickBot_motor_test.js deleted file mode 100755 index ed6435b3..00000000 --- a/books/beaglebone-cookbook/09capes/code/quickBot_motor_test.js +++ /dev/null @@ -1,116 +0,0 @@ -#!/usr/bin/env node -var b = require('bonescript'); -var M1_SPEED = 'P9_16'; // <1> -var M1_FORWARD = 'P8_15'; -var M1_BACKWARD = 'P8_13'; -var M2_SPEED = 'P9_14'; -var M2_FORWARD = 'P8_9'; -var M2_BACKWARD = 'P8_11'; -var freq = 50; // <2> -var fast = 0.95; -var slow = 0.7; -var state = 0; // <3> - -b.pinMode(M1_FORWARD, b.OUTPUT); // <4> -b.pinMode(M1_BACKWARD, b.OUTPUT); -b.pinMode(M2_FORWARD, b.OUTPUT); -b.pinMode(M2_BACKWARD, b.OUTPUT); -b.analogWrite(M1_SPEED, 0, freq); // <5> -b.analogWrite(M2_SPEED, 0, freq); - -updateMotors(); // <6> - -function updateMotors() { // <6> - //console.log("Setting state = " + state); // <7> - updateLEDs(state); // <7> - switch(state) { // <3> - case 0: - default: - M1_set(0); // <8> - M2_set(0); - state = 1; // <3> - break; - case 1: - M1_set(slow); - M2_set(slow); - state = 2; - break; - case 2: - M1_set(slow); - M2_set(-slow); - state = 3; - break; - case 3: - M1_set(-slow); - M2_set(slow); - state = 4; - break; - case 4: - M1_set(fast); - M2_set(fast); - state = 0; - break; - } - setTimeout(updateMotors, 2000); // <3> -} - -function updateLEDs(state) { // <7> - switch(state) { - case 0: - b.digitalWrite("USR0", b.LOW); - b.digitalWrite("USR1", b.LOW); - b.digitalWrite("USR2", b.LOW); - b.digitalWrite("USR3", b.LOW); - break; - case 1: - b.digitalWrite("USR0", b.HIGH); - b.digitalWrite("USR1", b.LOW); - b.digitalWrite("USR2", b.LOW); - b.digitalWrite("USR3", b.LOW); - break; - case 2: - b.digitalWrite("USR0", b.LOW); - b.digitalWrite("USR1", b.HIGH); - b.digitalWrite("USR2", b.LOW); - b.digitalWrite("USR3", b.LOW); - break; - case 3: - b.digitalWrite("USR0", b.LOW); - b.digitalWrite("USR1", b.LOW); - b.digitalWrite("USR2", b.HIGH); - b.digitalWrite("USR3", b.LOW); - break; - case 4: - b.digitalWrite("USR0", b.LOW); - b.digitalWrite("USR1", b.LOW); - b.digitalWrite("USR2", b.LOW); - b.digitalWrite("USR3", b.HIGH); - break; - } -} - -function M1_set(speed) { // <8> - speed = (speed > 1) ? 1 : speed; // <9> - speed = (speed < -1) ? -1 : speed; - b.digitalWrite(M1_FORWARD, b.LOW); - b.digitalWrite(M1_BACKWARD, b.LOW); - if(speed > 0) { - b.digitalWrite(M1_FORWARD, b.HIGH); - } else if(speed < 0) { - b.digitalWrite(M1_BACKWARD, b.HIGH); - } - b.analogWrite(M1_SPEED, Math.abs(speed), freq); // <10> -} - -function M2_set(speed) { - speed = (speed > 1) ? 1 : speed; - speed = (speed < -1) ? -1 : speed; - b.digitalWrite(M2_FORWARD, b.LOW); - b.digitalWrite(M2_BACKWARD, b.LOW); - if(speed > 0) { - b.digitalWrite(M2_FORWARD, b.HIGH); - } else if(speed < 0) { - b.digitalWrite(M2_BACKWARD, b.HIGH); - } - b.analogWrite(M2_SPEED, Math.abs(speed), freq); -} diff --git a/books/beaglebone-cookbook/code b/books/beaglebone-cookbook/code new file mode 160000 index 00000000..269209bc --- /dev/null +++ b/books/beaglebone-cookbook/code @@ -0,0 +1 @@ +Subproject commit 269209bc64423a06e8caf11b91c7468805b287b2 -- GitLab