element14 Community
element14 Community
    Register Log In
  • Site
  • Search
  • Log In Register
  • Community Hub
    Community Hub
    • What's New on element14
    • Feedback and Support
    • Benefits of Membership
    • Personal Blogs
    • Members Area
    • Achievement Levels
  • Learn
    Learn
    • Ask an Expert
    • eBooks
    • element14 presents
    • Learning Center
    • Tech Spotlight
    • STEM Academy
    • Webinars, Training and Events
    • Learning Groups
  • Technologies
    Technologies
    • 3D Printing
    • FPGA
    • Industrial Automation
    • Internet of Things
    • Power & Energy
    • Sensors
    • Technology Groups
  • Challenges & Projects
    Challenges & Projects
    • Design Challenges
    • element14 presents Projects
    • Project14
    • Arduino Projects
    • Raspberry Pi Projects
    • Project Groups
  • Products
    Products
    • Arduino
    • Avnet Boards Community
    • Dev Tools
    • Manufacturers
    • Multicomp Pro
    • Product Groups
    • Raspberry Pi
    • RoadTests & Reviews
  • Store
    Store
    • Visit Your Store
    • Choose another store...
      • Europe
      •  Austria (German)
      •  Belgium (Dutch, French)
      •  Bulgaria (Bulgarian)
      •  Czech Republic (Czech)
      •  Denmark (Danish)
      •  Estonia (Estonian)
      •  Finland (Finnish)
      •  France (French)
      •  Germany (German)
      •  Hungary (Hungarian)
      •  Ireland
      •  Israel
      •  Italy (Italian)
      •  Latvia (Latvian)
      •  
      •  Lithuania (Lithuanian)
      •  Netherlands (Dutch)
      •  Norway (Norwegian)
      •  Poland (Polish)
      •  Portugal (Portuguese)
      •  Romania (Romanian)
      •  Russia (Russian)
      •  Slovakia (Slovak)
      •  Slovenia (Slovenian)
      •  Spain (Spanish)
      •  Sweden (Swedish)
      •  Switzerland(German, French)
      •  Turkey (Turkish)
      •  United Kingdom
      • Asia Pacific
      •  Australia
      •  China
      •  Hong Kong
      •  India
      •  Korea (Korean)
      •  Malaysia
      •  New Zealand
      •  Philippines
      •  Singapore
      •  Taiwan
      •  Thailand (Thai)
      • Americas
      •  Brazil (Portuguese)
      •  Canada
      •  Mexico (Spanish)
      •  United States
      Can't find the country/region you're looking for? Visit our export site or find a local distributor.
  • Translate
  • Profile
  • Settings
Vision Thing
  • Challenges & Projects
  • Project14
  • Vision Thing
  • More
  • Cancel
Vision Thing
Blog BeagleBone AI Survival Guide V3.18: PWM, I2C, Analog/Digital Read/Write, Vision AI, Video Text Overlays, Audio, & Hardware
  • Blog
  • Forum
  • Documents
  • Events
  • Polls
  • Files
  • Members
  • Mentions
  • Sub-Groups
  • Tags
  • More
  • Cancel
  • New
Join Vision Thing to participate - click to join for free!
  • Share
  • More
  • Cancel
Group Actions
  • Group RSS
  • More
  • Cancel
Engagement
  • Author Author: Sean_Miller
  • Date Created: 27 Oct 2019 3:47 PM Date Created
  • Views 20399 views
  • Likes 20 likes
  • Comments 75 comments
  • visionthingch
  • beaglebone ai
  • beagleboard
Related
Recommended

BeagleBone AI Survival Guide V3.18: PWM, I2C, Analog/Digital Read/Write, Vision AI, Video Text Overlays, Audio, & Hardware

Sean_Miller
Sean_Miller
27 Oct 2019

TABLE OF CONTENTS

  • INTRODUCTION
  • BBAI SETUP CHECKLIST
  • GOOD STUFF TO KNOW
  • PINMUXING
    • Pinmux Procedure
    • a BBAI compatible dts file
  • ANALOG INPUT
    • sys file pin mapping
  • I2C USE
  • PWM CONTROL
  • AUDIO
  • CREATING A RAM DISK
  • TRANSFERRING FILES TO AND FROM OTHER MACHINES
    • Cloud 9 Upload Feature
    • GitHub
    • wget
    • Windows Shared Directory
  • CODE EXAMPLES
    • Augmented blinkLED.js
    • classification.cpp
    • analogIn.c
    • i2cLCD.c
    • tfmini.c
    • pwmout.c
    • servoPot.c
  • HARDWARE
    • Peripherals
    • Board Connector Original Images From the System Manual
    • Power and Ground Pins
    • Hardware Good Stuff to Know
  • AI VISION WITH TIDL
    • What is TIDL
    • TIDL Utils
    • More TIDL Examples
    • TIDL API
  • .NET 5 CORE INSTALLATION
  • REFERENCES
  • SURVIVAL GUIDE CHANGE LOG
image

 

**NEEDED CONTENT:  THE ONLY THING LEFT - HOW TO TRAIN IMAGES FOR THE CLASSIFICATION.TIDL.CPP FILE. 

PLEASE COMMENT IF YOU HAVE ANY LEADS**

INTRODUCTION

As of December 2019, the BeagleBone AI (BBAI) software is presently in an early community development state.  It requires a certain combination of a kernel version, code tweaks, and trial and error pin settings to get the packaged examples working.  The official system reference on GitHub has many "TBD/TODO" statements for the critical functionality of the board.  Several tables are for the BeagleBone Black which are not matched to the BBAI chipset.  The time-tested BeagleBoard code libraries at the time of hardware release are still developed for the past architectures.  So, I converted my hours of research here in hopes to save some time for other BeagleBoard beginners like myself with the desire to explore the BBAI.

 

Way below are some key references to keep your eye on as the BBAI develops.  Last, for document versioning of this blog, I'll use this convention to keep track of changes to this blog:  Whole versions for when new software is added, decimal versions when I change the instructions only, and no version increments if I'm just correcting my Kentucky English.

 

BBAI SETUP CHECKLIST

 

  1. Download the latest image - be sure it is for BeagleBone AI:
    https://beagleboard.org/latest-images
    (https://debian.beagleboard.org/images/am57xx-debian-10.3-iot-tidl-armhf-2020-04-06-6gb.img.xz)
  2. Burn it with Etcher to an SD card 8 to 32 Gig.  (other sizes have reported problems)
    https://www.techspot.com/downloads/6931-etcher.html
    BeagleBoard.org - getting-started
  3. Put the card in BBAI, power it, and connect PC to it using wifi SSID BeagleBoneXXXX and password BeagleBone. Connect to Cloud9 by navigating to 192.168.8.1.
  4. Follow on screen instructions in cloud9 to connect BBAI to your home wifi summarized here (if prompted for a root password, use temppwd - the default user is debian):
    sudo connmanctl⏎
    scan wifi⏎  (wait for response)
    services⏎ (copy the long string representing your wifi)
    agent on⏎
    connect <paste your string>⏎
    quit⏎
  5. Get the max storage capacity out of your SD Card:
    sudo /opt/scripts/tools/grow_partition.sh⏎
    sudo reboot⏎
  6. Get latest Cloud9 Examples:
    cd /var/lib/cloud9⏎
    git pull⏎ (in Cloud9, rightclick on the BeagleBone directory and click refresh to get the tidl directory)
  7. Get latest updates:
    sudo apt update⏎
    sudo apt upgrade⏎
  8. Download the MPGStreamer for use with embedded vision projects
    sudo apt install -y ti-tidl mjpg-streamer-opencv-python⏎
  9. Install Jason Kridner's perl package to show BeagleBone AI Pins (see useful commands below):
    sudo apt install libinline-files-perl⏎
  10. Install an even better package to show pins by Matt Van Duin:
    cd /usr/local/sbin⏎
    sudo wget -N https://raw.githubusercontent.com/mvduin/bbb-pin-utils/bbai-experimental/show-pins⏎
    sudo chmod a+x show-pins⏎
  11. Install BoneScript and setup a pin for use:
    cd /usr/local/lib⏎
    sudo npm install --unsafe-perm bonescript@0.7.4-beta1⏎
    node -pe "require('bonescript').bone.getPinObject('p9.15').ai.gpio"   (this sets up the pin in /sys/class/gpio)
  12. Update the Kernal - Note be sure to stay in the 4.14x range or the classification.cpp example will not work.
    cd /opt/scripts⏎
    git pull⏎
    sudo tools/update_kernel.sh⏎
  13. Update /var/lib/cloud9/BeagleBone/AI/tidl code to get a flashing LED:

        blinkLED.py (this is because the Adafruit Python Library is still mapped to the BeagleBone Black)
               out="P8_13" #actually 8_22 on BBAI, line 14
                    or
               out="P8_39" #for pin 9_15 on BBAI, line 14

 

blinkLED.js

const leds = ["USR3", "P9_15"];  //change line 13 to this to get processing improvement.

  14.  Perform the Pimuxing Procedure a couple of sections below.

  15.  Use Win32DiskImager to make a backup of your SD card.

 

GOOD STUFF TO KNOW

  • BBAI means BeagleBone AI (artificial intelligence).  BBB means BeagleBone Black.
  • Cloud9 is the development environment that you get when at Step 3 above.  It is scary at first, but you'll love it after a week playing with it.  It sustains your session.  So, you can jump from one computer to another hours later and start where you left off.  It also provides an editor that makes the Linux nano editor seem decades old ;-).
  • To add code to Cloud9, just right click on an existing directory such as the AI folder under Beaglebone on the left and then select "new file".
  • There are two pin headers on the BBAI.  With the ethernet port on top, P9 is on the left and P8 is on the right.  Pins are often referred to in the format P9.2, which would be the top right pin of the left header when oriented such that the ethernet port is on top.
  • Anytime I say "type", I mean type in a Linux terminal window.  You can pull up a new terminal window in Cloud9 by right clicking over a folder such as the AI folder and selecting "new terminal here".  The current directory will be the folder you right clicked on.
  • Dropping executables in the "autorun" directory in Cloud9 will have them start on boot up, theoretically.  I haven't pulled that off, yet.
  • PinMuxing means to configure the pin multiplexing of the BeagleBone chip to establish the optimal pin configuration of the headers that matches the peripherals that you will be using such as I2C devices, servos, leds, switches, etc.
  • The "/sys" directory is a virtual directory in memory.  You'll use subdirectories within it to set pins, but since its in memory, you don't have to be worried about read and writing a million times like you would an SD card.  In fact, your programming language calls are identical to how you would access an SD card file.  It's unsettling, but works well even for PWM.
  • The show-pins utilities and BeagleBone Adafruit IO library are mismatched to the pin names because they are still developed for the BeagleBone Black which has a different chipset.
  • You should only type "sudo" if you are doing something under the /boot or /lib directory.  Don't do it for most "git" calls or you'll set root access required permissions to those local folders.  So, if in doubt, don't use sudo unless you are told to by the system in response to not using it.
  • If you accidentally use sudo on a git repository that you shouldn't have, use sudo chown -R debian: the_folder, where debian is your username and the_folder is the folder created when you made the repository.  This will strip the root permission requirement back off of it.
  • In C, PWM settings on pins are set with fprintf in /sys/class/pwm/.  Type "ls /sys/class/pwm/" to study it from the bash window.
  • In C, Digital GPIO pins can be set through fprintf at /sys/class/gpio/.  Use the spreadsheet in the References to understand the cross reference from P9.X notation and the integer you see like gpiochip128 (which is P9.12).  Do "ls /sys/class/gpio/" to study it from the bash window.

 

USEFUL COMMANDS

  • Show pin configuration (aka the pinmux) - note the pin IDs in column 2 are off due to architecture differences with the BBB
    /opt/scripts/device/bone/show-pins.pl⏎ or
    show-pins⏎
  • Show BoneScript Version
    node -pe "require('bonescript').getPlatform().bonescript"⏎
  • Show Debian Image Date
    cat /etc/dogtag⏎
  • Show kernel and boot up device tree info
    sudo /opt/scripts/tools/version.sh⏎
  • Show an internal pin number as BoneScript sees it and set it up for access from code
    node -pe "require('bonescript').bone.getPinObject('p9.15').ai.gpio"⏎
  • Install the 4.14x kernel if you accidentally went to 4.19+ (which will cause classification.cpp to fail)
    sudo /opt/scripts/tools/update_kernel.sh --lts-4_14 --ti-channel⏎
  • Auto run a debugged application at startup by copying to the cloud9 directory:
    cp <filename> /var/lib/cloud9/
  • Show your entire directory structure on the Workspace Tab of Cloud9.  Type the statements below in the terminal.  You can name "root_link" anything you like.  After you enter in those comands, on the left in that Workspace Tab, scroll up until you see Favorites.  Click the "gear" icon on the upper right of that section.  Note:  the gear is often hidden, you have to float your mouse over the top right of the Workspace section.  Check the box "Show Home in Favorites":

cd ~

ln -s / root_link

  • Show attached cameras:

v4l2-ctl --list-devices⏎

  • Free up the Heap when your TIDL app fails from prior CTRL-c's:

ti-mct-heap-check -c⏎

 

PINMUXING

Pinmux Procedure

To get your GPIO to work from your code, you need to configure the pins as inputs, outputs, I2C, and PWM.  This is a process called Pinmuxing (pin multiplexing).  Here is a procedure for setting your pinmux configuration to the one that was used for my board:

cd ~ #(or wherever you want to clone the next line to)
git clone https://github.com/beagleboard/BeagleBoard-DeviceTrees -b v4.14.x-ti
nano BeagleBoard-DeviceTrees/src/arm/am5729-beagleboneai-custom.dts #(paste the dts file below)
cd ../../BeagleBoard-DeviceTrees
make src/arm/am5729-beagleboneai-custom.dtb
sudo cp src/arm/am5729-beagleboneai-custom.dtb /boot/dtbs
sudo nano /boot/uEnv.txt #(configure: dtb=am5729-beagleboneai-custom.dtb)
sudo reboot

 

a BBAI compatible dts file

A dts file (Device Tree Source) is what configures your Pinmux.  To match my setup used in this blog, use the Pinmux Procedure in the previous section and paste the text below in the nano editor at step 3.

#include "am5729-beagleboneai.dts"
// make it easy to determine which dtb you're currently running on
// (via /proc/device-tree/chosen/)
/ {
 chosen {
  base_dtb = "am5729-beagleboneai-custom.dts";
  base_dtb_timestamp = __TIMESTAMP__;
 };
};
// eventually these should be available in a header
#define P9_14  (0x3400 + 4 * 107)
#define P9_16  (0x3400 + 4 * 108)
#define P9_19a (0x3400 + 4 * 16)
#define P9_19b (0x3400 + 4 * 95)
#define P9_20a (0x3400 + 4 * 17)
#define P9_20b (0x3400 + 4 * 94)
// enable i2c-3 on P9.19 (scl) + P9.20 (sda)
&i2c4 {
 status = "okay";
 clock-frequency = <400000>;
 pinctrl-names = "default";
 pinctrl-0 = <&i2c4_pins>;
};
&dra7_pmx_core {
 i2c4_pins: i2c4 {
  pinctrl-single,pins = <
   DRA7XX_CORE_IOPAD( P9_19a, PIN_INPUT_PULLUP | MUX_MODE7  )  // scl
   DRA7XX_CORE_IOPAD( P9_19b, PIN_INPUT_PULLUP | MUX_MODE14 )  // (shared pin)
   DRA7XX_CORE_IOPAD( P9_20a, PIN_INPUT_PULLUP | MUX_MODE7  )  // sda
   DRA7XX_CORE_IOPAD( P9_20b, PIN_INPUT_PULLUP | MUX_MODE14 )  // (shared pin)
  >;
 };
};
// enable pwm-2 on P9.14 (out-A) + P9.16 (out-B)
&epwmss2 {
 status = "okay";
};
&ehrpwm2 {
 status = "okay";
 pinctrl-names = "default";
 pinctrl-0 = <&ehrpwm2_pins>;
};
&dra7_pmx_core {
 ehrpwm2_pins: ehrpwm2 {
  pinctrl-single,pins = <
   DRA7XX_CORE_IOPAD( P9_14, PIN_OUTPUT_PULLDOWN | MUX_MODE10 )  // out A
   DRA7XX_CORE_IOPAD( P9_16, PIN_OUTPUT_PULLDOWN | MUX_MODE10 )  // out B
  >;
 };
};

// Here's the obnoxious part: since u-boot doesn't have same pin defaults yet, all pins not
// explicitly setup above should be overridden here.  This will eventually no longer be needed.
&cape_pins_default {
 pinctrl-single,pins = <
  DRA7XX_CORE_IOPAD( 0x372C, PIN_INPUT_PULLDOWN | MUX_MODE15 ) // P9.11a (no gpio)
  DRA7XX_CORE_IOPAD( 0x3620, PIN_INPUT          | MUX_MODE14 ) // P9.11b
  DRA7XX_CORE_IOPAD( 0x36AC, PIN_INPUT_PULLDOWN | MUX_MODE14 ) // P9.12
  DRA7XX_CORE_IOPAD( 0x3730, PIN_INPUT_PULLDOWN | MUX_MODE15 ) // P9.13  (no gpio)
 // DRA7XX_CORE_IOPAD( 0x35AC, PIN_INPUT_PULLDOWN | MUX_MODE14 ) // P9.14
  DRA7XX_CORE_IOPAD( 0x3514, PIN_INPUT_PULLDOWN | MUX_MODE14 ) // P9.15
 // DRA7XX_CORE_IOPAD( 0x35B0, PIN_INPUT_PULLDOWN | MUX_MODE14 ) // P9.16
  DRA7XX_CORE_IOPAD( 0x37CC, PIN_INPUT_PULLDOWN | MUX_MODE14 ) // P9.17a
  DRA7XX_CORE_IOPAD( 0x36B8, PIN_INPUT          | MUX_MODE14 ) // P9.17b
  DRA7XX_CORE_IOPAD( 0x37C8, PIN_INPUT_PULLDOWN | MUX_MODE14 ) // P9.18a
  DRA7XX_CORE_IOPAD( 0x36B4, PIN_INPUT          | MUX_MODE14 ) // P9.18b
 // DRA7XX_CORE_IOPAD( 0x3440, PIN_INPUT_PULLUP   | MUX_MODE14 ) // P9.19a
 // DRA7XX_CORE_IOPAD( 0x357C, PIN_INPUT          | MUX_MODE14 ) // P9.19b
 // DRA7XX_CORE_IOPAD( 0x3444, PIN_INPUT_PULLUP   | MUX_MODE14 ) // P9.20a
 // DRA7XX_CORE_IOPAD( 0x3578, PIN_INPUT          | MUX_MODE14 ) // P9.20b
  DRA7XX_CORE_IOPAD( 0x34F0, PIN_INPUT_PULLDOWN | MUX_MODE14 ) // P9.21a
  DRA7XX_CORE_IOPAD( 0x37C4, PIN_INPUT          | MUX_MODE14 ) // P9.21b
  DRA7XX_CORE_IOPAD( 0x369C, PIN_INPUT_PULLDOWN | MUX_MODE14 ) // P9.22a
  DRA7XX_CORE_IOPAD( 0x37C0, PIN_INPUT          | MUX_MODE14 ) // P9.22b
  DRA7XX_CORE_IOPAD( 0x37B4, PIN_INPUT_PULLUP   | MUX_MODE14 ) // P9.23
  DRA7XX_CORE_IOPAD( 0x368C, PIN_INPUT_PULLUP   | MUX_MODE14 ) // P9.24
  DRA7XX_CORE_IOPAD( 0x3694, PIN_INPUT_PULLDOWN | MUX_MODE14 ) // P9.25
  DRA7XX_CORE_IOPAD( 0x3688, PIN_INPUT_PULLUP   | MUX_MODE14 ) // P9.26a
  DRA7XX_CORE_IOPAD( 0x3544, PIN_INPUT          | MUX_MODE14 ) // P9.26b
  DRA7XX_CORE_IOPAD( 0x35A0, PIN_INPUT_PULLDOWN | MUX_MODE14 ) // P9.27a
  DRA7XX_CORE_IOPAD( 0x36B0, PIN_INPUT          | MUX_MODE14 ) // P9.27b
  DRA7XX_CORE_IOPAD( 0x36E0, PIN_INPUT_PULLDOWN | MUX_MODE14 ) // P9.28
  DRA7XX_CORE_IOPAD( 0x36D8, PIN_INPUT_PULLDOWN | MUX_MODE14 ) // P9.29a
  DRA7XX_CORE_IOPAD( 0x36A8, PIN_INPUT          | MUX_MODE14 ) // P9.29b
  DRA7XX_CORE_IOPAD( 0x36DC, PIN_INPUT_PULLDOWN | MUX_MODE14 ) // P9.30
  DRA7XX_CORE_IOPAD( 0x36D4, PIN_INPUT_PULLDOWN | MUX_MODE14 ) // P9.31a
  DRA7XX_CORE_IOPAD( 0x36A4, PIN_INPUT          | MUX_MODE14 ) // P9.31b
  DRA7XX_CORE_IOPAD( 0x36A0, PIN_INPUT_PULLDOWN | MUX_MODE14 ) // P9.41a
  DRA7XX_CORE_IOPAD( 0x3580, PIN_INPUT          | MUX_MODE14 ) // P9.41b
  DRA7XX_CORE_IOPAD( 0x36E4, PIN_INPUT_PULLDOWN | MUX_MODE14 ) // P9.42a
  DRA7XX_CORE_IOPAD( 0x359C, PIN_INPUT          | MUX_MODE14 ) // P9.42b
  DRA7XX_CORE_IOPAD( 0x379C, PIN_INPUT_PULLUP   | MUX_MODE14 ) // P8.3
  DRA7XX_CORE_IOPAD( 0x37A0, PIN_INPUT_PULLUP   | MUX_MODE14 ) // P8.4
  DRA7XX_CORE_IOPAD( 0x378C, PIN_INPUT_PULLUP   | MUX_MODE14 ) // P8.5
  DRA7XX_CORE_IOPAD( 0x3790, PIN_INPUT_PULLUP   | MUX_MODE14 ) // P8.6
  DRA7XX_CORE_IOPAD( 0x36EC, PIN_INPUT_PULLDOWN | MUX_MODE14 ) // P8.7
  DRA7XX_CORE_IOPAD( 0x36F0, PIN_INPUT_PULLDOWN | MUX_MODE14 ) // P8.8
  DRA7XX_CORE_IOPAD( 0x3698, PIN_INPUT_PULLDOWN | MUX_MODE14 ) // P8.9
  DRA7XX_CORE_IOPAD( 0x36E8, PIN_INPUT_PULLDOWN | MUX_MODE14 ) // P8.10
  DRA7XX_CORE_IOPAD( 0x3510, PIN_INPUT_PULLDOWN | MUX_MODE14 ) // P8.11
  DRA7XX_CORE_IOPAD( 0x350C, PIN_INPUT_PULLDOWN | MUX_MODE14 ) // P8.12
  DRA7XX_CORE_IOPAD( 0x3590, PIN_INPUT_PULLDOWN | MUX_MODE14 ) // P8.13
  DRA7XX_CORE_IOPAD( 0x3598, PIN_INPUT_PULLDOWN | MUX_MODE14 ) // P8.14
  DRA7XX_CORE_IOPAD( 0x3570, PIN_INPUT_PULLDOWN | MUX_MODE14 ) // P8.15a
  DRA7XX_CORE_IOPAD( 0x35B4, PIN_INPUT          | MUX_MODE14 ) // P8.15b
  DRA7XX_CORE_IOPAD( 0x35BC, PIN_INPUT_PULLDOWN | MUX_MODE14 ) // P8.16
  DRA7XX_CORE_IOPAD( 0x3624, PIN_INPUT_PULLDOWN | MUX_MODE14 ) // P8.17
  DRA7XX_CORE_IOPAD( 0x3588, PIN_INPUT_PULLDOWN | MUX_MODE14 ) // P8.18
  DRA7XX_CORE_IOPAD( 0x358C, PIN_INPUT_PULLDOWN | MUX_MODE14 ) // P8.19
  DRA7XX_CORE_IOPAD( 0x3780, PIN_INPUT_PULLUP   | MUX_MODE14 ) // P8.20
  DRA7XX_CORE_IOPAD( 0x377C, PIN_INPUT_PULLUP   | MUX_MODE14 ) // P8.21
  DRA7XX_CORE_IOPAD( 0x3798, PIN_INPUT_PULLUP   | MUX_MODE14 ) // P8.22
  DRA7XX_CORE_IOPAD( 0x3794, PIN_INPUT_PULLUP   | MUX_MODE14 ) // P8.23
  DRA7XX_CORE_IOPAD( 0x3788, PIN_INPUT_PULLUP   | MUX_MODE14 ) // P8.24
  DRA7XX_CORE_IOPAD( 0x3784, PIN_INPUT_PULLUP   | MUX_MODE14 ) // P8.25
  DRA7XX_CORE_IOPAD( 0x35B8, PIN_INPUT_PULLDOWN | MUX_MODE14 ) // P8.26
  DRA7XX_CORE_IOPAD( 0x35D8, PIN_INPUT_PULLDOWN | MUX_MODE14 ) // P8.27a
  DRA7XX_CORE_IOPAD( 0x3628, PIN_INPUT          | MUX_MODE14 ) // P8.27b
  DRA7XX_CORE_IOPAD( 0x35C8, PIN_INPUT_PULLDOWN | MUX_MODE14 ) // P8.28a
  DRA7XX_CORE_IOPAD( 0x362C, PIN_INPUT          | MUX_MODE14 ) // P8.28b
  DRA7XX_CORE_IOPAD( 0x35D4, PIN_INPUT_PULLDOWN | MUX_MODE14 ) // P8.29a
  DRA7XX_CORE_IOPAD( 0x3630, PIN_INPUT          | MUX_MODE14 ) // P8.29b
  DRA7XX_CORE_IOPAD( 0x35CC, PIN_INPUT_PULLDOWN | MUX_MODE14 ) // P8.30a
  DRA7XX_CORE_IOPAD( 0x3634, PIN_INPUT          | MUX_MODE14 ) // P8.30b
  DRA7XX_CORE_IOPAD( 0x3614, PIN_INPUT_PULLDOWN | MUX_MODE14 ) // P8.31a
  DRA7XX_CORE_IOPAD( 0x373C, PIN_INPUT_PULLDOWN | MUX_MODE15 ) // P8.31b (no gpio)
  DRA7XX_CORE_IOPAD( 0x3618, PIN_INPUT_PULLDOWN | MUX_MODE14 ) // P8.32a
  DRA7XX_CORE_IOPAD( 0x3740, PIN_INPUT_PULLDOWN | MUX_MODE15 ) // P8.32b (no gpio)
  DRA7XX_CORE_IOPAD( 0x3610, PIN_INPUT_PULLDOWN | MUX_MODE14 ) // P8.33a
  DRA7XX_CORE_IOPAD( 0x34E8, PIN_INPUT          | MUX_MODE14 ) // P8.33b
  DRA7XX_CORE_IOPAD( 0x3608, PIN_INPUT_PULLDOWN | MUX_MODE14 ) // P8.34a
  DRA7XX_CORE_IOPAD( 0x3564, PIN_INPUT          | MUX_MODE14 ) // P8.34b
  DRA7XX_CORE_IOPAD( 0x360C, PIN_INPUT_PULLDOWN | MUX_MODE14 ) // P8.35a
  DRA7XX_CORE_IOPAD( 0x34E4, PIN_INPUT          | MUX_MODE14 ) // P8.35b
  DRA7XX_CORE_IOPAD( 0x3604, PIN_INPUT_PULLDOWN | MUX_MODE14 ) // P8.36a
  DRA7XX_CORE_IOPAD( 0x3568, PIN_INPUT          | MUX_MODE14 ) // P8.36b
  DRA7XX_CORE_IOPAD( 0x35FC, PIN_INPUT_PULLDOWN | MUX_MODE14 ) // P8.37a
  DRA7XX_CORE_IOPAD( 0x3738, PIN_INPUT_PULLDOWN | MUX_MODE15 ) // P8.37b (no gpio)
  DRA7XX_CORE_IOPAD( 0x3600, PIN_INPUT_PULLDOWN | MUX_MODE14 ) // P8.38a
  DRA7XX_CORE_IOPAD( 0x3734, PIN_INPUT_PULLDOWN | MUX_MODE15 ) // P8.38b (no gpio)
  DRA7XX_CORE_IOPAD( 0x35F4, PIN_INPUT_PULLDOWN | MUX_MODE14 ) // P8.39
  DRA7XX_CORE_IOPAD( 0x35F8, PIN_INPUT_PULLDOWN | MUX_MODE14 ) // P8.40
  DRA7XX_CORE_IOPAD( 0x35EC, PIN_INPUT_PULLDOWN | MUX_MODE14 ) // P8.41
  DRA7XX_CORE_IOPAD( 0x35F0, PIN_INPUT_PULLDOWN | MUX_MODE14 ) // P8.42
  DRA7XX_CORE_IOPAD( 0x35E4, PIN_INPUT_PULLDOWN | MUX_MODE14 ) // P8.43
  DRA7XX_CORE_IOPAD( 0x35E8, PIN_INPUT_PULLDOWN | MUX_MODE14 ) // P8.44
  DRA7XX_CORE_IOPAD( 0x35DC, PIN_INPUT_PULLDOWN | MUX_MODE14 ) // P8.45a
  DRA7XX_CORE_IOPAD( 0x361C, PIN_INPUT          | MUX_MODE14 ) // P8.45b
  DRA7XX_CORE_IOPAD( 0x35E0, PIN_INPUT_PULLDOWN | MUX_MODE14 ) // P8.46a
  DRA7XX_CORE_IOPAD( 0x3638, PIN_INPUT          | MUX_MODE14 ) // P8.46b
 >;
};

 

After doing the Pinmux procedure above and rebooting, you can show the pin configuration:

Note: the pin IDs shown in the second column are easily confused for GPIO references.  For example, P9.15 is 76 versus 69.  From the author of the spreadsheet, P9.15 connects to the net "AG4_GPIO3_12" which connects to VIN1A_D8 (ball AG4) of the AM572x.  From the AM572x TRM: CTRL_CORE_PAD_VIN1A_D8 is at 0x4A003514, which is byte-offset 0x114 into the pinmux array, i.e. index 0x114/4 = 69.  Thanks to Matthijs van Duin for the first hand info.

 

 

debianaglebone:~$ sudo show-pins                                                                                                                 
[sudo] password for debian:
Caution: Uses peripheral names from <https://goo.gl/jiazTL>. See README there for details.
P9.19a                                16 fast rx  up   7 i²c 3 scl        i2c@4807a000 (i2c4)
P9.20a                                17 fast rx  up   7 i²c 3 sda        i2c@4807a000 (i2c4)
P8.35b                                57 fast rx      14 gpio 2.00
P8.33b                                58 fast rx      14 gpio 2.01
P9.21a                                60 fast rx down 14 gpio 2.03
P8.12                                 67 fast rx down 14 gpio 2.10
P8.11                                 68 fast rx down 14 gpio 2.11
P9.15                                 69 fast rx down 14 gpio 2.12 lo >>  sysfs
P9.26b                                81 fast rx      14 gpio 2.24
P8.34b                                89 fast rx      14 gpio 3.00
P8.36b                                90 fast rx      14 gpio 3.01
P8.15a                                92 fast rx down 14 gpio 3.03
P9.20b                                94 fast rx  up  14 gpio 3.05        i2c@4807a000 (i2c4)
P9.19b                                95 fast rx  up  14 gpio 3.06        i2c@4807a000 (i2c4)
P9.41b                                96 fast rx      14 gpio 3.07
P8.18                                 98 fast rx down 14 gpio 3.09
P8.19                                 99 fast rx down 14 gpio 3.10
P8.13                                100 fast rx down 14 gpio 3.11
P8.14                                102 fast rx down 14 gpio 3.13
P9.42b                               103 fast rx      14 gpio 3.14
P9.27a                               104 fast rx down 14 gpio 3.15
P9.14                                107 fast    down 10 pwm 2 A          pwm@48442200 (ehrpwm2)
P9.16                                108 fast    down 10 pwm 2 B          pwm@48442200 (ehrpwm2)
P8.15b                               109 fast rx      14 gpio 3.27
P8.26                                110 fast rx down 14 gpio 3.28
P8.16                                111 fast rx down 14 gpio 3.29
P8.28a                               114 fast rx down 14 gpio 3.19
P8.30a                               115 fast rx down 14 gpio 3.20
P8.29a                               117 fast rx down 14 gpio 3.22
P8.27a                               118 fast rx down 14 gpio 3.23
P8.45a                               119 fast rx down 14 gpio 7.00
P8.46a                               120 fast rx down 14 gpio 7.01
P8.43                                121 fast rx down 14 gpio 7.02
P8.44                                122 fast rx down 14 gpio 7.03
P8.41                                123 fast rx down 14 gpio 7.04
P8.42                                124 fast rx down 14 gpio 7.05
P8.39                                125 fast rx down 14 gpio 7.06
P8.40                                126 fast rx down 14 gpio 7.07
P8.37a                               127 fast rx down 14 gpio 7.08
P8.38a                               128 fast rx down 14 gpio 7.09
P8.36a                               129 fast rx down 14 gpio 7.10
P8.34a                               130 fast rx down 14 gpio 7.11
P8.35a                               131 fast rx down 14 gpio 7.12
P8.33a                               132 fast rx down 14 gpio 7.13
P8.31a                               133 fast rx down 14 gpio 7.14
P8.32a                               134 fast rx down 14 gpio 7.15
P8.45b                               135 fast rx      14 gpio 7.16
P9.11b                               136 fast rx      14 gpio 7.17
P8.17                                137 fast rx down 14 gpio 7.18
P8.27b                               138 fast rx      14 gpio 7.19
P8.28b                               139 fast rx      14 gpio 7.20
P8.29b                               140 fast rx      14 gpio 7.21
P8.30b                               141 fast rx      14 gpio 7.22
P8.46b                               142 fast rx      14 gpio 7.23
P9.13b ?                             160 fast    down 15 unused          
P9.26a                               162 fast rx  up  14 gpio 5.14
P9.24                                163 fast rx  up  14 gpio 5.15
P9.25                                165 fast rx down 14 gpio 5.17
P8.09                                166 fast rx down 14 gpio 5.18
P9.22a                               167 fast rx down 14 gpio 5.19
P9.41a                               168 fast rx down 14 gpio 5.20
P9.31b                               169 fast rx      14 gpio 6.31
P9.29b                               170 fast rx      14 gpio 6.30
P9.12                                171 fast rx down 14 gpio 4.00 << lo  sysfs
P9.27b                               172 fast rx      14 gpio 4.01
P9.18b                               173 fast rx      14 gpio 4.02
P9.17b                               174 fast rx      14 gpio 4.03
P9.31a                               181 fast rx down 14 gpio 4.10
P9.29a                               182 fast rx down 14 gpio 4.11
P9.30                                183 fast rx down 14 gpio 4.12
P9.28                                184 fast rx down 14 gpio 3.17
P9.42a                               185 fast rx down 14 gpio 3.18
P8.10                                186 fast rx down 14 gpio 5.04
P8.07                                187 fast rx down 14 gpio 5.05
P8.08                                188 fast rx down 14 gpio 5.06
P9.11a                               203 fast rx down 15 unused          
P9.13a                               204 fast rx down 15 unused          
P8.38b                               205 fast rx down 15 unused          
P8.37b                               206 fast rx down 15 unused          
P8.31b                               207 fast rx down 15 unused          
P8.32b                               208 fast rx down 15 unused          
P8.21                                223 fast rx  up  14 gpio 5.29
P8.20                                224 fast rx  up  14 gpio 5.30
P8.25                                225 fast rx  up  14 gpio 5.31
P8.24                                226 fast rx  up  14 gpio 6.00
P8.05                                227 fast rx  up  14 gpio 6.01
P8.06                                228 fast rx  up  14 gpio 6.02
P8.23                                229 fast rx  up  14 gpio 0.22
P8.22                                230 fast rx  up  14 gpio 0.23
P8.03                                231 fast rx  up  14 gpio 0.24
P8.04                                232 fast rx  up  14 gpio 0.25
P9.23                                237 fast rx  up  14 gpio 6.11
P9.22b                               240 fast rx      14 gpio 6.14
P9.21b                               241 fast rx      14 gpio 6.15
P9.18a                               242 fast rx down 14 gpio 6.16
P9.17a                               243 fast rx down 14 gpio 6.17

 

Above you can see that Pin 9.15 and 9.12 are in use by my augmented blinkLED.js program shown in the Code Examples section below.  The << means that P9.12 is an input and the >> means that P9.15 is an output.  In this case, 12 is detecting no voltages (LOW), and in turn, my code is outputting LOW.

 

ANALOG INPUT

Analog input is useful for communicating a degree of magnitude from a component.  It is actually the least used way to get input by me for any project I've ever done.  In fact, I have only used it with potentiometers to communicate desired servo position or audio volume.  Some older sensors, though, would use it to communicate the measured value within their output range.  You would do math on the microcontroller to ratio that input to a useful value such as distance.

 

Although the utility show-pins doesn't show it and the spreadsheet referenced in the References section doesn't reflect it, pin P9.33 is an analog in paired to "in_voltage7_raw" in the "sys" folder.  It reads 0-1.8V and outputs a range of 0-2000ish.  I found it testing the output as shown here:

debian@beaglebone:/var/lib/cloud9/BeagleBone/AI/backupcamera$ cat /sys/bus/iio/devices/iio:device0/in_voltage7_raw #jumper between P9.33 and P9.01 (GND)
0

debian@beaglebone:/var/lib/cloud9/BeagleBone/AI/backupcamera$ cat /sys/bus/iio/devices/iio:device0/in_voltage7_raw #jumper between P9.33 and P9.03 (3.3V)
4095

 

With this we can simply read using any language that reads a text file.  See analogIn.c in Code Examples below.

 

Note, the ADC reads up to 1.8Vs which can be supplied to your components reference voltage by Pin 9.32 (For example, the voltage for a potentiometer).  However, I did test 3.3V on the analog in pins and it gave a stable 4095 as the return value.  Thanks to Fred Bogardus, he confirmed that the ADC of 1.8V is for backwards compatibility with older Beagle boards.  The AI will take 3.3V since the STMPE811QTR can handle 3.3V on the analog in as shown on this schematic:

image

STMPE811QTR Schematic

 

sys file pin mapping

I could only safely locate 3 pins for analog read, although the spreadsheet shows 8.

/sys/bus/iio/devices/iio:device0/in_voltage7_raw     P9.33

/sys/bus/iio/devices/iio:device0/in_voltage4_raw     P9.35

/sys/bus/iio/devices/iio:device0/in_voltage6_raw     P9.36

 

 

I2C USE

I2C (Inter-Intergrated Circuit) is a serial communication protocol that allows a device to talk to many, many I2C compatible devices with just two pins, called the clock and data lines.  They are commonly found for talking to LCD Displays and sensors.  As found in the show-pins output above, pins 9.19 and 9.20 are I2C enabled SCL and SDA pins, respectively.  You can test this by hooking up an I2C device of your choice such as an I2C enabled LCD Display.  Run the i2cdetect command as shown here:

 

debian@beaglebone:~$ i2cdetect -r 3
WARNING! This program can confuse your I2C bus, cause data loss and worse!
I will probe file /dev/i2c-3 using read byte commands.
I will probe address range 0x03-0x77.
Continue? [Y/n] y
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- 27 -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --
debian@beaglebone:~$

 

My LCD Display address for i2C is x27 which received a confirmed hit with i2cdetect as shown above.  See Code Examples for an I2C LCD c program.

 

PWM CONTROL

PWM stands for Pulse Width Modulation.  It reminds me of Morse code at a high speed frequency.  It provides a means to communicate with other devices typically to relay a magnitude you desire of a given parameter such as speed, degrees of rotation, or audio volume.  It is very common for sending a fine tuned pulsed signal that can be interpreted by a servo to determine its position.  It can also be used to imply an analog signal between 0-3.3V such as for the input of a transistor driving a DC motor.

 

Digging around the "/sys/class" directory, I found /sys/class/pwm/pwm-0:0 relates to P9.14 when you use the Pinmux procedure provided earlier in this blog.  See pwmout.c in Code Examples below for an example of controlling it.  It's a three step process:   set the frequency, set the duty, then enable the pin.

 

AUDIO

Unlike the Raspberry Pi, the BBAI doesn't have a headphone jack.  To enable sound from the BBAI USB port, you first need a USB-to-Audio cable to hook to an external speaker (see the Hardware section for a link to one).  To enable it on the system, you need to create a sound config file.  To create it, type the following at a terminal screen:

nano ~/.asoundrc

 

Then paste the following in the nano editor:

 

pcm.!default {  
        type plug  
        slave {  
                pcm "hw:1,0"  
        }  
}  
ctl.!default {  
        type hw  
        card 1  
} 

 

To test it, you need a file.  To get an epic one quickly, type the following in the terminal:

wget https://goo.gl/CDF6sf -O ./audio-sample.wav

 

Then play it with:

aplay ./audio-sample.wav

 

If you can't hear anything, list your detected hardware and type:

aplay -l

 

It may show your card as "2" instead of "1".  edit the ./asoudrc file to change all 1's to a 2.

 

Then, from your C or C++ code, you can play sound files on demand like with a line like this:

system("sudo -u debian aplay -q /yourpath/yourfile.wav &");

 

The reason for the "sudo -u" trick is that Cloud9 will run your app as root which for some reason prevents the audio from playing.  This trick will get your sound out your speaker.  The -q will play it without it piping output to the terminal and the & sumbol will play the sound as a separate process so your code doesn't stall waiting for the sound to complete.

 

 

CREATING A RAM DISK

Once you start making a complex robot of some sort, you will find that you may want services running.  These are programs that have one function such as updating a text file with the local weather forecast every half hour.  Rather than writing one big application that does all the sensor poling and IoT communication, you can have several services that can be leveraged into any number of projects.  The fastest performance in this approach is to store the data those services acquire to a RAM Disk.  You can then retrieve it by your main application at light speed without worry of corrupting an SD card due to hitting it every millisecond.

 

To create a RAM disk, first create a directory where you want it.  For example, at the terminal type:

mkdir ~/ramdisk

sudo chmod +777 ~/ramdisk

 

Then, to have your ram disk available everytime you reboot, type the following:

sudo nano /etc/fstab

 

Paste the following at the bottom of the screen and press CTRL-x to save:

myramdisk  /home/debian/ramdisk  tmpfs  defaults,size=64k,x-gvfs-show  0  0

 

This will give you a 64k ram disk.  You may want it bigger for your needs.

 

Remember, RAM disappears after a reboot or power cycle.  So, don't store anything you want to keep here.  It is solely for communication between your programs in an uber modular fashion.  Use your standard file methods in your language of choice to use it.

 

TRANSFERRING FILES TO AND FROM OTHER MACHINES

There will be a time you will want a file outside of your BBAI such as from a Windows PC on your network.  Most commonly, this would be sound files, image files, and code.  I have narrowed this down to the four easiest options:  1) Cloud9 Upload Feature, 2) Github, 3) wget, and 4) a Windows Shared folder.

 

Cloud 9 Upload Feature

The quickest way to get an external file to the BBAI is with the Cloud9 IDE.  Here are the steps to do so:

  1. In the Cloud9 IDE, left click on the directory where you want the files to land.
  2. On the menu bar, click File-->Upload Local Files
  3. Browse out either a single file or a directory.

 

To get a file from the BBAI to your local machine running Cloud9, just right click it and select Download.

 

GitHub

I've grown to be a big fan of Github since it can backup my code and I can deploy it to multiple devices.  I don't have to worry about bricking a device and losing everything I was developing.  So, another option is to keep all your files and code in Github and do git clone <repository>.  You can then upload files from Windows to Github and then pull them in to your BBAI repository.

 

wget

If the file can be served from a http: source, you can just open a terminal, cd to the directory where you want to place it, and then type wget <URL>

 

Windows Shared Directory

Last, if you want to access a Windows directory from a terminal running on the BBAI, you'll need a package that let's you see Windows Shared Folders on your network.

 

Type the following in your terminal:

sudo apt-get install cifs-utils

Let it install.  No need to reboot.

 

Create a Linux directory to hold the share folder:

     cd ~

     mkdir windows

 

Then, to mount the drive in Linux on your BBAI, type the following:

     sudo mount.cifs "//windowscomputername/windowsfolderpath" "windows" -o user=yourwindowsusername

 

You can name the "windows" directory whatever you want as long as you did a mkdir that matches.  You can now browse the directory with Linux terminal commands.  Of course, the Windows computer better be turned on!

 

 

CODE EXAMPLES

Below are working code examples that make use of the PinMux Procedure earlier in this blog.  One extra thing to note is that when you click run on a .c or .cpp file, you must then change the "runner" of Cloud9 and then click run again.  Do this as shown in the boxed rectangle in the picture here:

image

Setting the Runner in Cloud 9 for C and C++

 

To use this code, you can right click in the Cloud9 IDE on a directory of choice and select New File.  You can name it what you like.  Be sure the extension matches the programming language, though.  (js for javascript files, c for C files, cpp for C++, py for Python).  After pasting the code in the new empty file, press CTRL s to save and click the run button as desribed above.

 

Augmented blinkLED.js

adds demonstration of digital read as well as write.  See comments section for wiring and setup.

#!/usr/bin/env node
////////////////////////////////////////
// blinkLED.js
//      Blinks the USR LEDs and P9_15 when you connect 3.3V to P9_12.
// Wiring: P9_15 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.  A jumper goes in the 3.3V header (not 5V!).  Other end goes into
//         P_12.  Take it in and out to watch light turn on.
// Setup:  first type the following into the terminal to set up your pins if you haven't...
//          node -pe "require('bonescript').bone.getPinObject('P9.12').ai.gpio"
//          node -pe "require('bonescript').bone.getPinObject('P9.15').ai.gpio"
//  Issues: On first execution, it may through and error due to permissions.  Try running
//          again.
////////////////////////////////////////
const b = require('bonescript');
const leds = ["USR3", "P9_15"];
for(var i in leds) {
    b.pinMode(leds[i], b.OUTPUT);
}
b.pinMode("P9_12",b.INPUT);
var state = b.HIGH;
for(var i in leds) {
    b.digitalWrite(leds[i], state);
}
setInterval(toggle, 100);
function toggle() {
    if (b.digitalRead("P9_12")==b.HIGH) 
        state = b.HIGH;
    else
        state = b.LOW;
    for(var i in leds) {
        b.digitalWrite(leds[i], state);
    }
}

 

classification.cpp

add the following else case shown on line 15 to get text even when an object is not seen.

if(is_object >= 0)  //excerpt from cloud9/BeagleBone/AI/tidl/classification.cpp, Line 310
    {
        cv::putText(
            dst,
            (*(labels_classes[is_object])).c_str(),
            cv::Point(15, 60),
            cv::FONT_HERSHEY_SIMPLEX,
            1.5,
            cv::Scalar(0,255,0),
            3,  /* thickness */
            8
        );
    }
    //new code is below that allows for a constant message or tweaking as you see fit.
    else
    {
        char my_message[]="Searching...";
        cv::putText(
            dst,
            my_message,
            cv::Point(30, 60),
            cv::FONT_HERSHEY_SIMPLEX,
            1.5,
            cv::Scalar(0,255,0),
            3,  /* thickness */
            8
        );
    }
    //end of new code

 

analogIn.c

program to show how to read 0.3.3 voltage on an analog input pin with C

////////////////////////////////////////
// analogIn.c
//      reports 0-3.3V on P9.33 as 0-4095
//  Author:  Sean J. Miller
//  Wiring: Jumper a 0-3.3V source to P9.33
//
// See: https://www.element14.com/community/community/designcenter/single-board-computers/next-genbeaglebone/blog/2019/10/27/beagleboard-ai-brick-recovery-procedure
////////////////////////////////////////
#include <stdio.h>
#include <unistd.h>


int analogRead(){
     FILE * my_in_pin = fopen("/sys/bus/iio/devices/iio:device0/in_voltage7_raw", "r");//P9.33 on the BBAI
     char the_voltage[5];//the characters in the file are 0 to 4095
     fgets(the_voltage,6,my_in_pin);
     fclose(my_in_pin);
     printf("Voltage:  %s\n", the_voltage);
     return 0;
}


int main() {
     while(1) {
          analogRead();
         usleep(1000000);
      }
}

 

i2cLCD.c

program to demonstrate talking to an I2C device.  In this case, an LCD.

/* ----------------------------------------------------------------------- *
 * Title:         i2clcd                                                   *
 * Description:   C-code for PCF8574T backpack controlling LCD through I2C *
 *                Tested on BeagleBone AI                                  *
 *                11/1/2019 Sean Miller                                    *
 * ported from:                                                            *
 * https://github.com/fm4dd/i2c-lcd/blob/master/pcf8574-lcd-demo.c         *
 *                             *
 * Compilation:   i2clcd.c -o i2clcd                                       *
 *------------------------------------------------------------------------ */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <linux/i2c-dev.h>
#include <fcntl.h>


#define I2C_BUS        "/dev/i2c-3" // I2C bus device
#define I2C_ADDR       0x27         // I2C slave address for the LCD module
#define BINARY_FORMAT  " %c  %c  %c  %c  %c  %c  %c  %c\n"
#define BYTE_TO_BINARY(byte) \
  (byte & 0x80 ? '1' : '0'), \
  (byte & 0x40 ? '1' : '0'), \
  (byte & 0x20 ? '1' : '0'), \
  (byte & 0x10 ? '1' : '0'), \
  (byte & 0x08 ? '1' : '0'), \
  (byte & 0x04 ? '1' : '0'), \
  (byte & 0x02 ? '1' : '0'), \
  (byte & 0x01 ? '1' : '0') 
  
int lcd_backlight;
int debug;
char address; 
int i2cFile;


void i2c_start() {
   if((i2cFile = open(I2C_BUS, O_RDWR)) < 0) {
      printf("Error failed to open I2C bus [%s].\n", I2C_BUS);
      exit(-1);
   }
   // set the I2C slave address for all subsequent I2C device transfers
   if (ioctl(i2cFile, I2C_SLAVE, I2C_ADDR) < 0) {
      printf("Error failed to set I2C address [%s].\n", I2C_ADDR);
      exit(-1);
   }
}


void i2c_stop() { close(i2cFile); }


void i2c_send_byte(unsigned char data) {
   unsigned char byte[1];
   byte[0] = data;
   if(debug) printf(BINARY_FORMAT, BYTE_TO_BINARY(byte[0]));
   write(i2cFile, byte, sizeof(byte)); 
   /* -------------------------------------------------------------------- *
    * Below wait creates 1msec delay, needed by display to catch commands  *
    * -------------------------------------------------------------------- */
   usleep(1000);
}


void main() { 
   i2c_start(); 
   debug=0; //change to 1 to see messages.


   /* -------------------------------------------------------------------- *
    * Initialize the display, using the 4-bit mode initialization sequence *
    * -------------------------------------------------------------------- */
   if(debug) printf("Init Start:\n");


   usleep(15000);             // wait 15msec
   i2c_send_byte(0b00110100); // D7=0, D6=0, D5=1, D4=1, RS,RW=0 EN=1
   i2c_send_byte(0b00110000); // D7=0, D6=0, D5=1, D4=1, RS,RW=0 EN=0
   usleep(4100);              // wait 4.1msec
   i2c_send_byte(0b00110100); // 
   i2c_send_byte(0b00110000); // same
   usleep(100);               // wait 100usec
   i2c_send_byte(0b00110100); //
   i2c_send_byte(0b00110000); // 8-bit mode init complete
   usleep(4100);              // wait 4.1msec
   i2c_send_byte(0b00100100); //
   i2c_send_byte(0b00100000); // switched now to 4-bit mode


   /* -------------------------------------------------------------------- *
    * 4-bit mode initialization complete. Now configuring the function set *
    * -------------------------------------------------------------------- */
   usleep(40);                // wait 40usec
   i2c_send_byte(0b00100100); //
   i2c_send_byte(0b00100000); // keep 4-bit mode
   i2c_send_byte(0b10000100); //
   i2c_send_byte(0b10000000); // D3=2lines, D2=char5x8


   /* -------------------------------------------------------------------- *
    * Next turn display off                                                *
    * -------------------------------------------------------------------- */
   usleep(40);                // wait 40usec
   i2c_send_byte(0b00000100); //
   i2c_send_byte(0b00000000); // D7-D4=0
   i2c_send_byte(0b10000100); //
   i2c_send_byte(0b10000000); // D3=1 D2=display_off, D1=cursor_off, D0=cursor_blink


   /* -------------------------------------------------------------------- *
    * Display clear, cursor home                                           *
    * -------------------------------------------------------------------- */
   usleep(40);                // wait 40usec
   i2c_send_byte(0b00000100); //
   i2c_send_byte(0b00000000); // D7-D4=0
   i2c_send_byte(0b00010100); //
   i2c_send_byte(0b00010000); // D0=display_clear


   /* -------------------------------------------------------------------- *
    * Set cursor direction                                                 *
    * -------------------------------------------------------------------- */
   usleep(40);                // wait 40usec
   i2c_send_byte(0b00000100); //
   i2c_send_byte(0b00000000); // D7-D4=0
   i2c_send_byte(0b01100100); //
   i2c_send_byte(0b01100000); // print left to right


   /* -------------------------------------------------------------------- *
    * Turn on the display                                                  *
    * -------------------------------------------------------------------- */
   usleep(40);                // wait 40usec
   i2c_send_byte(0b00000100); //
   i2c_send_byte(0b00000000); // D7-D4=0
   i2c_send_byte(0b11100100); //
   i2c_send_byte(0b11100000); // D3=1 D2=display_on, D1=cursor_on, D0=cursor_blink


   if(debug) printf("Init End.\n");
   sleep(1);


   if(debug) printf("Writing HELLO to display\n");
   if(debug) printf("D7 D6 D5 D4 BL EN RW RS\n");


   /* -------------------------------------------------------------------- *
    * Start writing 'H' 'E' 'L' 'L' 'O' chars to the display, with BL=on.  *
    * -------------------------------------------------------------------- */
   i2c_send_byte(0b01001101); //
   i2c_send_byte(0b01001001); // send 0100=4
   i2c_send_byte(0b10001101); //
   i2c_send_byte(0b10001001); // send 1000=8 = 0x48 ='H'


   i2c_send_byte(0b01001101); //
   i2c_send_byte(0b01001001); // send 0100=4
   i2c_send_byte(0b01011101); // 
   i2c_send_byte(0b01011001); // send 0101=1 = 0x41 ='E'


   i2c_send_byte(0b01001101); //
   i2c_send_byte(0b01001001); // send 0100=4
   i2c_send_byte(0b11001101); //
   i2c_send_byte(0b11001001); // send 1100=12 = 0x4D ='L'


   i2c_send_byte(0b01001101); //
   i2c_send_byte(0b01001001); // send 0100=4
   i2c_send_byte(0b11001101); //
   i2c_send_byte(0b11001001); // send 1100=12 = 0x4D ='L'


   i2c_send_byte(0b01001101); //
   i2c_send_byte(0b01001001); // send 0100=4
   i2c_send_byte(0b11111101); //
   i2c_send_byte(0b11111001); // send 1111=15 = 0x4F ='O'


   if(debug) printf("Finished writing to display.\n");
   i2c_stop(); 
}

tfmini.c

This program will talk to an I2C enabled TFmini LIDAR distance sensor.

/* ----------------------------------------------------------------------- *
 * Title:         tfmini.c                                                 *
 * Description:   C-code for TFMini Plus                                   *
 *                Tested on BeagleBone AI                                  *
 *                11/6/2019 Sean J. Miller                                 *
 * Prerequisites:                             *
 *------------------------------------------------------------------------ */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <linux/i2c-dev.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <string.h>
#define I2C_BUS        "/dev/i2c-3" // I2C bus device
#define I2C_ADDR       0x10         // I2C slave address for the TFMini module
int debug;
int i2cFile;
void i2c_start() {
   if((i2cFile = open(I2C_BUS, O_RDWR)) < 0) {
      printf("Error failed to open I2C bus [%s].\n", I2C_BUS);
      exit(-1);
   } else {
       if (debug)printf("Opened I2C Bus\n");
   }
   // set the I2C slave address for all subsequent I2C device transfers
   if (ioctl(i2cFile, I2C_SLAVE, I2C_ADDR) < 0) {
      printf("Error failed to set I2C address [%s].\n", I2C_ADDR);
      exit(-1);
   } else {
      printf("Set Slave Address\n");
   }
}
void i2c_stop() { close(i2cFile); }
float readDistance() {
 //Routine to output the distance to the console
 int distance = 0; //distance
 int strength = 0; // signal strength
 int rangeType = 0; //range scale
 unsigned char incoming[7]; //an array of bytes to hold the returned data from the TFMini.
 unsigned char cmdBuffer[] = { 0x01, 0x02, 7 }; //the bytes to send the request of distance
 
   write( i2cFile, cmdBuffer, 3 );
   usleep(100000);
   read(i2cFile, incoming, 7);
 for (int x = 0; x < 7; x++)
 {
  if (x == 0)
  {
   //Trigger done
   if (incoming[x] == 0x00)
   {
   
   }
   else if (incoming[x] == 0x01)
   {
   
   }
  }
  else if (x == 2)
   distance = incoming[x]; //LSB of the distance value "Dist_L"
  else if (x == 3)
   distance |= incoming[x] << 8; //MSB of the distance value "Dist_H"
  else if (x == 4)
   strength = incoming[x]; //LSB of signal strength value
  else if (x == 5)
   strength |= incoming[x] << 8; //MSB of signal strength value
  else if (x == 6)
   rangeType = incoming[x]; //range scale
 }
 
 float the_return = distance / (12 * 2.54); //convert to feet.
 return the_return;
}
void main() {
   i2c_start(); 
   debug=1; //change to 1 to see messages.

   if(debug) printf("Init Start:\n");
   float my_distance = readDistance();
   if(debug) printf("the_distance: %f\n",my_distance);
   if(debug) printf("Finished reading.\n");
   i2c_stop();
   if(debug) printf("Finshed, Sean!\n\n");
}

pwmout.c

a program that will swell an LED on P9.14 using PWM

////////////////////////////////////////
//  pwmout.c
//      generates pwm on a pin to glow an LED
//  Author:  Sean J. Miller
//  Wiring: Jumper P9.14 to an LED through a 220ohm resistor to ground
//
// See: https://www.element14.com/community/community/designcenter/single-board-computers/next-genbeaglebone/blog/2019/10/27/beagleboard-ai-brick-recovery-procedure
////////////////////////////////////////
#include <stdio.h>
#include <unistd.h>


void setupPWM() {
    FILE *period, *pwm;
    pwm = fopen("/sys/class/pwm/pwm-0:0/enable", "w");
    fseek(pwm,0,SEEK_SET);
    fprintf(pwm,"%d",1);
    fflush(pwm);
    fclose(pwm);
    
    printf("Period...!\n");
    period = fopen("/sys/class/pwm/pwm-0:0/period", "w");
    fseek(period,0,SEEK_SET);
    fprintf(period,"%d",2500);
    fflush(period);
    fclose(period);
    
}
void pwm_duty(int the_duty_multiplier)
{
    FILE *duty;
    duty = fopen("/sys/class/pwm/pwm-0:0/duty_cycle", "w");
    fseek(duty,0,SEEK_SET);
    fprintf(duty,"%d",100*the_duty_multiplier);
    fflush(duty);
    fclose(duty);
}


int main() {
     int ii=0;int up=0;
     printf("Setting up\n");
     setupPWM();
     
     while(1) {
        printf("Swelling LED %d\n",ii);
         if (up==1) ii++; else ii--;
         if ((ii)>60) {
             up=0;
         }
         if (ii<3) {
             up=1;
         }
         pwm_duty(ii);
         usleep(25000);
      }
}

 

servoPot.c

reads a potentiometer and translates it to a servo's position

////////////////////////////////////////
//  servoPot.c
//      reads a pot and translates it to
//      a servos position.
//  Author:  Sean J. Miller, 11/3/2019
//  Wiring: Jumper P9.14 to a servo signal through a 220ohm resistor
//          Hook a potentiometers variable voltage to P9.33 (analog in).  It's source should be Pin 32 (VDADC of 1.8V)
//  See: https://www.element14.com/community/community/designcenter/single-board-computers/next-genbeaglebone/blog/2019/10/27/beagleboard-ai-brick-recovery-procedure
////////////////////////////////////////
#include <stdio.h>
#include <unistd.h>
int analogRead(){
    int i;
    FILE * my_in_pin = fopen("/sys/bus/iio/devices/iio:device0/in_voltage7_raw", "r");//P9.33 on the BBAI
    char the_voltage[5];//the characters in the file are 0 to 4095
    fgets(the_voltage,6,my_in_pin);
    fclose(my_in_pin);
    printf("Voltage:  %s\n", the_voltage);
    sscanf(the_voltage, "%d", &i);
    return (i);
}


void setupPWM() {
    FILE *period, *pwm;
    pwm = fopen("/sys/class/pwm/pwm-0:0/enable", "w");
    fseek(pwm,0,SEEK_SET);
    fprintf(pwm,"%d",1);
    fflush(pwm);
    fclose(pwm);
    
    
    period = fopen("/sys/class/pwm/pwm-0:0/period", "w");
    fseek(period,0,SEEK_SET);
    fprintf(period,"%d",20000000);//20ms
    fflush(period);
    fclose(period);
    
}
void pwm_duty(int the_duty_multiplier)
{
    FILE *duty; int duty_calc;
    duty = fopen("/sys/class/pwm/pwm-0:0/duty_cycle", "w");
    fseek(duty,0,SEEK_SET);
    duty_calc=(600000 + (1700000*(float)((float)the_duty_multiplier/4095))) ;
    printf("Duty: %d\n", duty_calc);//1ms
    fprintf(duty,"%d",duty_calc);//1ms
    fflush(duty);
    fclose(duty);
}


int main() {
     int ii=0;
     printf("Setting up\n");
     setupPWM();
     
     while(1) {
        ii=analogRead();
        pwm_duty(ii);
        usleep(20000);
     }
}

HARDWARE

Peripherals

Below are the hardware components that will help you get the most out of the board:

3 Pin Serial Debug Connector3 Pin Serial Debug Connector - probably don't need it, but its an alternative to using WiFi for "headless" interaction with the BBAI.

Pins for 3 Pin Serial Debug ConnectorPins for 3 Pin Serial Debug Connector - probably don't need it, but its an alternative to using WiFi for "headless" interaction with the BBAI.

3A USB C Power Plug3A USB C Power Plug - the BBAI needs at least 2.5 As to stay stable

Cooling FanCooling Fan - needed to prevent overheating and sporadic shutdown

Cooling Fan Machine Screws Size:  M3

$9 Web Cam - great little cheap web cam for your Visual AI projects

USB to Audio Cable - enables audio

USB 4 Port HubUSB 4 Port Hub - allows to connect audio and multiple web cams at same time.

Board Connector Original Images From the System Manual

imageimage

Power and Ground Pins

DGND: this is the digital ground to connect any digital devices

GNDA_ADC: this is the analog ground used to connect any devices that return an analog signal such as a potentiometer

VDD_3V3 - use this to power 3.3v electronics

VDD_5V - use this to power the beagleboard (i.e. through a barrel jack, if you are going to put one on the cape/shield), NOT to power 5V electronics

SYS_5V - use this to power 5V electronics

VDD_ADC - use to connect power analog in devices such as Potentiometers.  (It is 1.8V for backwards compatibility as discussed in the Analog Input section.)

image

BeagleBone Black Pin Reference: 

It's pretty much the same, but things are not setup out of the box for use.

See the PinMux Procedure Section above.

Hardware Good Stuff to Know

  • PWR_BUT is 3.3V level as pulled up internally by the TPS6590379. It is activated by pulling the signal to GND.  It won't do a soft Power Off like the BB Black did, but it will turn it on after a shutdown command.

  • GPIO max current is still a mystery.  I couldn't find it on the ARM 572 Sitara docs, yet.  Some BBB tutorials stated a 8mA limit - which seems safe compared to other microcontrollers.  So, I use a transistor as a switch to handle the load of any components that are doing anything but high impedance signal communication.  For example, LEDs, Piezos, and DC motors should be transistor switched.  Between the GPIO and transistor I use a 420 ohm current limiting resistor to keep the current under 8ma according to ohm's law.

AI VISION WITH TIDL

What is TIDL

At this point, I am just enough to be dangerous with making use of the TIDL acceleration of the BBAI through the modification of the classification.cpp example.  As I learn, I'll add to this section what I gather.  Let's begin...

 

The TI Deep Learning (TIDL) API allows for embedded devices to use TI’s proprietary, highly optimized neural implementation on the EVE and C66x DSP compute engines.  This means you can get frame fast classification of your trained objects for your exact application - whether it be detecting abnormalities in microscope images of cells or assessing if you left the oven on. 

The TIDL API leverages TI’s OpenCLTm product to offload deep learning applications to both EVEs and DSPs. This allows us to not fool with the mechanics of ArmRegistered Left right arrow DSP/EVE communication and implementing optimized network layers on EVE(s) and/or DSP(s).  We can use OpenCV and rapidly code deep learning applications.

One thing to note, if you are not using the TIDL API for your Vision AI apps, such as by porting over Raspberry Pi OpenCV code, then you are not using the accelerated TIDL hardware.  You're not gaining a thing.

Here is the development workflow for TIDL apps:

image

TIDL Development Workflow

Panels 1 and 2 are the mystery for me now.  Unfortunately, TI's link is presently broken on how to do those steps:

http://software-dl.ti.com/processor-sdk-linux/esd/docs/latest/linux/Foundational_Components_TIDL.html

TIDL Utils

From a tip from @mander1, there appears to be utilities for importing tensorflow models available.  I'm still trying to figure it out, but here is how you get it:

     git clone https://git.ti.com/git/tidl/tidl-utils.git

 

This readme.txt states how to set up your environment variables in Linux:  /tidl/tidl-utils/src/importTool/readme.txt

 

You can then type "make" in the following directory to compile the import tool:

/tidl/tidl-utils/src/importTool/modules/ti_dl/utils/tidlModelImport

 

More to come on this hopeful way of getting trained models available to the TIDL API.

 

More TIDL Examples

After installing the TIDL examples per the checklist at the beginning of this blog, you'll find more TIDL examples tucked away than what shows in Cloud9.  You can them locate with the following:

cd /usr/share/ti/examples/tidl

ls

 

I found that I had to use sudo to run the examples.  A full description of the examples can be found here:

     Examples — TIDL API User's Guide

 

When running the examples, you may run into an error shown below.  There is a utility you can run that will free up the heap to correct it.  Below shows me working through this experience:

debian@beaglebone:/usr/share/ti/examples/tidl/two_eo_per_frame$ sudo ./two_eo_per_frame
two_eo_per_frame: inc/executor.h:172: T* tidl::malloc_ddr(size_t) [with T = char; size_t = unsigned int]: Assertion `val != nullptr' failed.
debian@beaglebone:/usr/share/ti/examples/tidl/two_eo_per_frame$ ti-mct-heap-check -c
-- ddr_heap1 ------------------------------
   Addr : 0xa2000000
   Size : 0x16000000
   Avail: 0x16000000
   Align: 0x80
-----------------------------------------
debian@beaglebone:/usr/share/ti/examples/tidl/two_eo_per_frame$ sudo ./two_eo_per_frame
PASSED

 

TIDL API

Texas instruments provides a good high level overview and the terminology of the TIDL API here:

Overview — TIDL API User's Guide

 

One good thing, there are only 4 C++ classes to learn:   Configuration, Executor, ExecutionObject, and ExecutionObjectPipeline.  In turn, you can tell code a mile away that doesn't make use of the hardware if you don't see the header files for them at the start of the code.

 

TI Software-I'm just scouting this one, but I think it might get us to generating trained images for the BBAI.

PROCESSOR-SDK-TDAX Processor SDK for TDAx ADAS SoCs - Linux and TI-RTOS Support | TI.com

 

.NET 5 CORE INSTALLATION

If you like to code in C# with .Net, you can install dotnet for Linux.  The actual installation of the dotnet binaries is easy and quick.  I made an Instructable here on how to do it as well as set up a .Net 5 Core web server with your BBAI:

https://www.instructables.com/Build-a-Very-Cheap-Net-5-Core-Web-Server-With-Beag/

 

REFERENCES

  • https://github.com/beagleboard - Main BB github repository
  • BeagleBoard.org - latest-images - Latest Debian Images
  • https://github.com/beagleboard/bb.org-overlays - BeagleBone Kernel References
  • https://www.hackster.io/175809/tidl-on-beaglebone-ai-1ee263#toc-make-sure-the-tidl-library-and-examples-are-installed-2 - Vision AI example
  • https://www.elinux.org/EBC_Exercise_41_Pin_Muxing_for_the_AI - shows how to set up pins on board, but always bricks mine!
  • https://groups.google.com/forum/embed/?place=forum/beagleboard&showsearch=true&showpopout=true&showtabs=false&hideforumt… - BeagleBone Forum
  • https://training.ti.com/texas-instruments-deep-learning-tidl-overview - How to train the vision AI for the BBAI's Texas Instruments chipset
  • http://BeagleBoard.org/chat - live chat with the board creators
  • https://github.com/jadonk/bonescript - BoneScript API
  • https://docs.google.com/spreadsheets/d/1fE-AsDZvJ-bBwzNBj1_sPDrutvEvsmARqFwvbw_HkrE/edit?usp=sharing- spreadsheet showing pin IDs and other useful info for pinmux configuration.
  • Accessing GPIO and PWM on BeagleBone AI - e14 Discussion that is trying to sort out GPIO use for the BBAI
  • https://github.com/beagleboard/cloud9-examples/issues/18 - issue created on beagleboard github on cloud9 examples not working
  • https://github.com/adafruit/adafruit-beaglebone-io-python/issues/317 - Adafruit Github Issue created concerning python examples not working
  • https://github.com/mvduin/bbb-pin-utils/tree/bbai-experimental#show-pins - a good utility for viewing pin configuration of your board.
  • https://cdn-learn.adafruit.com/downloads/pdf/introduction-to-the-beaglebone-black-device-tree.pdf - all about device tree source files.
  • BBAI Seein' Around Corners, Talkin', IoT Exploitin' Backup Car Cam with Onboard Vision AI - example BBAI project
  • Instructables - Build a Very Cheap .Net 5 Core Web Server with a BBAI - .Net 5 Core Instructables
  • https://www.youtube.com/channel/UCXAfHSB_IhaKhntZ4bWfmbw - my youtube channel of projects.
  • https://github.com/beagleboard/beaglebone-ai/wiki/System-Reference-Manual- the under development reference manual on GitHub.
  • BeagleBone AI BB-AI Photos for Documentation Purposes - excellent share by shabaz.
  • https://blogs.nvidia.com/blog/2016/07/29/whats-difference-artificial-intelligence-machine-learning-deep-learning-ai/- great article on the history of AI, Machine Learning, and Deep Learning
  • A Beginning Journey in TensorFlow #1:  Regression
  • Introduction — TIDL API User's Guide

 

SURVIVAL GUIDE CHANGE LOG

05/29/2921:  V3.18 Added link to how to install .Net Core 5 and a .Net webserver

05/28/2021:  V3.17 Update link for the current image and listed default passwords.  Wishing I had a nickel for every time I bricked it.

06/28/2020:  V3.16 updated the Power and Ground pins to reflect the V3.14 learning on analog pins.

06/02/2020:  V3.15 corrected info on the returned output from the show-pins utility.

04/29/2020:  V3.14 confirmed that 3.3V is acceptable for analog in versus just 1.8V.  Credit to Fred Bogardus for the confirmation!

01/03/2020:  V3.13 added how to get and compile the tidl utilities for importing models.  Added how to have Cloud9 show directories at the root and beyond.

12/15/2019:  V3.12 added more file transferring techniques using Cloud9, Github, and wget

11/19/2019:  V3.11 added Creating a RAM Disk Section

11/18/2019:  V3.10 added Exploring AI Vision with TIDL section

11/17/2019:  V3.9 added a cd at Pinmux procedure to change the directory for the make statement to work

11/16/2019:  V3.8 added more general definitions throughout to eliminate assumptions of experience level

11/13/2019:  V3.7 added Sharing Files with a Window PC

11/13/2019:  V3.6 added Audio section and linked a webcam under $10 and a cheap USB-to-Audio cable in the Hardware section.

11/09/2019:  V3.5 added pinout picture under hardware and warnings that the ADC is 1.8Vs which can be supplied by pin P9.32.

11/09/2019:  V3.4 added board images for pin reference in Hardware section as well as hardware good stuff to know.  Also, gave link to system manual

11/07/2019:  V3.3 added Hardware Add-ons Section

11/06/2019:  V3.2 added TFMini.c.  It shows how to read and write on I2C using a TFMini module.

11/03/2019:  V3.1 added servoPot.c code example.  It takes analog in from a potentiometer and translates it to a servo's position allowing you to control the servo with the potentiometer.

11/02/2019:  V3.0 added PWM section and pwmout.c code - all pin features are now achieved!!!!!!  Added Good Stuff to Know Section that sheds a lot of light on things.

11/02/2019:  V2.4 added analogIn.c example for reading analog in.

11/02/2019:  V2.3 added Analog Input Section

11/01/2019:  V2.2 added i2clcd.c code to demonstrate using I2C on bus 3

11/01/2019:  V2.1 added I2C section

10/31/2019:  V2.0 added Pinmuxing Section to show how to setup pins and added Matt Van Duin's show-pins utility to setup.  Move classification tweak to new Code Examples section.

10/31/2019:  V1.2 added augmented blinkLED.js code to demonstrate using digital read/write.

10/27/2019:  V1.1 added node -pe "require('bonescript').bone.getPinObject('p9.15').ai.gpio" to step 10.  It's needed to setup the pin for use.

10/27/2019:  V1.0 Published

  • Sign in to reply

Top Comments

  • Sean_Miller
    Sean_Miller over 5 years ago in reply to gibsonmb +3
    Long story short, if you don't do the pinmux procedure, you won't get far with the GPIO on the BBAI for reads, I2C, and PWM. The BBAI architecture is different from the Beaglebone Black, so past tutorials…
  • mander1
    mander1 over 5 years ago +3
    Hi - thanks for posting this extensive amount of useful information. This is my first post on Element14 in the hopes of getting up to speed on the BBAI's TIDL library. I posted the following already on…
  • sung
    sung over 5 years ago +3
    BBAI(Beaglebone AI) uart3_txd not working correctly Hi, ALL I have a problem with setup UART*. I'm trying to use pins P9.24 (uart10_txd) and P9.26 (uart10_rxd) as a UART on a BBAI with Debian 4.14.108…
  • persyn
    persyn over 3 years ago

    Hello,

     

    I am trying to control a robotic arm (4 servo's) with the beaglebone ai. I was able to generate a PWM signal on P9_14 trough the example pwmout.c but need 4 in total. I tried to control  /sys/class/pwm/pwm-0:1 instead of /sys/class/pwm/pwm-0:0  and expected to be able to PWM P9_16 but this doesn't work. Can someone help me how to control multiple (4) PWM signals with the beaglebone ai?

    • Cancel
    • Vote Up +1 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • Sean_Miller
    Sean_Miller over 4 years ago in reply to themysticturtle

    If I recall correctly, I think a Segmentation Fault error would appear if the "Runner" is not be set correctly in the Cloud 9 environment.  Look for that screen shot immediately under the Code Examples heading for how to set the Runner to verify.

     

    See ya',

    Sean

    • Cancel
    • Vote Up +1 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • themysticturtle
    themysticturtle over 4 years ago in reply to themysticturtle

    also, if i run your pwmout.c program. this is the error i get.  (and the code before it as well for accurate reference)

    Started /var/lib/cloud9/: pwmout.c

    File path: /var/lib/cloud9/BeagleBone/AI

    File: /var/lib/cloud9/BeagleBone/AI/pwmout.c

    Arguments:

    File name: pwmout.c

    File extension: c

    File base name: pwmout

    Packages: ~.c9/packages

    Project path: /var/lib/cloud9/

    Project name: projectname

    Hostname: localhost

    Hostname path: https://undefined/BeagleBone/AI/pwmout.c

    URL: http://localhost

    Port: 8080

    IP: 0.0.0.0

    Command: BeagleBone/AI/pwmout.c

    Python: python3

    Python path: /usr/lib/python3.7/dist-packages:/usr/local/lib/python3.7/dist-packages

    /var/lib/cloud9/common/Makefile:27: MODEL=BeagleBoard.org_BeagleBone_AI,TARGET=pwmout,COMMON=/var/lib/cloud9/common

    /var/lib/cloud9/common/Makefile:146: GEN_DIR=/tmp/cloud9-examples,CHIP=,PROC=arm,PRUN=,PRU_DIR=,EXE=.out

    ./pwmout.out

    Setting up

    make: *** [/var/lib/cloud9/common/Makefile:172: start] Segmentation fault

     




    • Cancel
    • Vote Up +1 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • themysticturtle
    themysticturtle over 4 years ago

    Hello! I have followed the tutorial (as it sits on 7/6/2021.. wow. are we really that far along in 2021?)  to set up the BBAI. including the pinmuxing.

    Now, i can see the data stream running analongInSync.js or analogInCallBack.js  using a simple phototransistor going from one of the VDD3v3B slots to the positive side, and taking my readings from the negative side hooked to P9.36 analog input. with the v- side of phototransistor also pulled to ground via 10kohm resistor.  (i get good results in the data feed on my cloud9 ide console, as well as when i view this output directly with my siglent oscilloscope)

    However, when i attempt to do the analogInOut.js. even after verifying my p9.14 and p9.16 are correctly muxed as PWM outputs with the show-pins command in console.

    "

    P9.14                                107 fast    down 10 pwm 2 A          pwm@48442200 (ehrpwm2)

    P9.16                                108 fast    down 10 pwm 2 B          pwm@48442200 (ehrpwm2)"

    I get an interesting error. " error: error updating PWM freq and value: undefined, Error: ENOENT: no such file or directory, open 'undefined/period' "

    Here is the code directly from the file i am attempting to run.


    ""
    #!/usr/bin/env node

    ////////////////////////////////////////

    // analogInOut.js

    //  Reads analog in on P9_36 and adjusts the PWM on P9_14.

    // Wiring: Attach the outer pins on a variable resistor to P9_32 and P9_34.

    //          Attach the wiper (middle pin) of the resistor to P9_36.

    //          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:

    ////////////////////////////////////////

    const b = require('bonescript');

     

     

    const inputPin  = "A5";

    const outputPin = "P9_14";

     

     

    console.log('Hit ^C to stop');

    b.pinMode(outputPin, b.ANALOG_OUTPUT);

    setTimeout(loop, 400);  // work-around to wait for PWM permissions

     

     

    function loop() {

        var value = b.analogRead(inputPin);

        process.stdout.write(inputPin + '-->' + outputPin + ': ' + (value*100).toFixed(1) + '%   \r');

        b.analogWrite(outputPin, value);

        setTimeout(loop, 10);

    }

     

     

    // Bone  | Pocket | AIN

    // ----- | ------ | ---

    // P9_39 | P1_19  | A0

    // P9_40 | P1_21  | A1

    // P9_37 | P1_23  | A2

    // P9_38 | P1_25  | A3

    // P9_33 | P1_27  | A4

    // P9_36 | P2_35  | A5

    // P9_35 | P1_02  | A6


    ""

    Any ideas why this is occurring?


    I am totally new to coding, and trying to figure this out. As far as i can tell. what is going on in this program is it calls up the bonescript. I am not entirely sure what bonescript is, but i imagine it allows everything on the beaglebone board to communicate with each other and route signals properly.

    then it sets a constant of A5. or P9-36 as an input pin.

    It also sets P9-14 PWM pin as an output pin constant.

    It sets the pin mode of our constant output pin. to analog_output.

    i am not sure what the set timeout does, but i imagine it delays the program erroring out to hopefully wait for the PWM permissions to activate (which i do not think mine are?)

    then it runs a loop of variable "value" = the analog read of our constant "input pin" 

    Then the process.stdout.write continually prints the information as the data is being retrieved. then it does inputpin + something + output pin + something + (value variable * 100).toFixed (no idea what that does x 1) + i have no earthly idea.
    Then it is supposed to analog write to the output pin, the value it calculated from that formula i do not understand.
    I assume the timeout is how long it has to accomplish this before the program errors out of it does not get a result.




    Please pardon my ignorance on the programming side of things. I specialize in hardware design. Fixtures/jigs/tools/cnc programing. Industrial manufacturing process optimization. And they also have me build custom automated industrial equipment they can not find for sale out here in the R&D lab.

    So far, i have cheated and used an RPI and matlab/simulink/stateflow.

    Now, my goal is to be able to run a touch screen based GUI (still with a physical/hard e-stop) to control this BBAI board.
    I have QT design studio, open source, and i am trying to learn how to actually code this and link a touch screen GUI to read and control various pins.  So it is finally time for me to learn some proper coding. (any advice or suggestions is always greatly appreciated)

    The end result of this first project will hopefully be a device to semi automate the process of pressure/water testing on some units we produce. I intend to have a differential pressure sensor sending in an analogue signal to do a PID type control of a blower motor to maintain the set PSF of vacuum or pressure. or follow a program.

    While the sensors collect data about temperature/humidity. relative atmospheric pressure vs dynamic test pressure. calculate CFM. and graph these values on some form of chart/report i can export to a local server folder.

    My previous contraptions were all button control panel based looking for GPIO inputs to change the machine behavior.

    Any insight, recommendations, or help with this would be greatly appreciated. I would be happy to assist you guys with any of your hardware design/cad cam/cnc programming/ pcb design and layout needs in return image

    Thank you all very much for your time, and your expertise. And a big shout out to @sean miller for taking the time and effort to put this tutorial together.
























    • Cancel
    • Vote Up +1 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • wojciech_jsiewicz
    wojciech_jsiewicz over 4 years ago in reply to sung

    Hi sung,

    Did you fix that problem with the UART interface?

    Best regards,
    Wojciech Jasiewicz.

    • Cancel
    • Vote Up +1 Vote Down
    • Sign in to reply
    • More
    • Cancel
>
element14 Community

element14 is the first online community specifically for engineers. Connect with your peers and get expert answers to your questions.

  • Members
  • Learn
  • Technologies
  • Challenges & Projects
  • Products
  • Store
  • About Us
  • Feedback & Support
  • FAQs
  • Terms of Use
  • Privacy Policy
  • Legal and Copyright Notices
  • Sitemap
  • Cookies

An Avnet Company © 2025 Premier Farnell Limited. All Rights Reserved.

Premier Farnell Ltd, registered in England and Wales (no 00876412), registered office: Farnell House, Forge Lane, Leeds LS12 2NE.

ICP 备案号 10220084.

Follow element14

  • X
  • Facebook
  • linkedin
  • YouTube