Thursday, January 30, 2014

Disable USB Ethernet on BeagleBone


I noticed that commenting out usb0 in /etc/network/interfaces doesn't disable usb ethernet.  But looking at the comments it suggests removing run_boot-scripts from /boot/uboot.  That worked.  If you need it back just
touch /boot/uboot/run_boot-scripts
However, this will also mess with USB so the cell modem doesn't work right.

Wednesday, January 29, 2014

Setting up USB Wifi with BeagleBone Black


Playing with using a USB wifi with my BeagleBone Black running Debian (helpful link).  First step was to make sure the driver was installed which it should be (apt-get install firmware-ralink).  Then uncomment /etc/network/interfaces per your need:
# WiFi Example
auto wlan0
iface wlan0 inet dhcp
    wpa-ssid "essid"
    wpa-psk  "password"

To prevent people from seeing your password change permissions to root only:

chmod 600 /etc/network/interfaces
Power down, install the USB Wifi and it should connect.

If you don't know the name of the ESSID you want you can scan for available wifi ports using the following:
iwlist wlan0 scanning | grep ESSID


Tuesday, January 28, 2014

Getting my USB modem to startup automatically

Working on getting the USB modem working on boot up with the beaglebone black.  Initially setup was blogged about here.  To accomplish this I created cellmodem.sh (with lots of online help) and put it in /etc/init.d.  Here is the code:

#! /bin/sh
### BEGIN INIT INFO
# Provides:          cellmodem
# Required-Start:    $all
# Required-Stop:     
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Start cell modem if ethernet is not connected
# Description:       Start cell modem if ethernet is not connected
### END INIT INFO

#
# Function that starts the daemon/service
#
do_start()
{
        ipAddress=`/sbin/ifconfig eth0 | grep "inet addr" | cut -d":" -f2 | cut -d" " -f1`
        echo "$ipAddress"
        ipLength=`expr length "$ipAddress"`
        echo $ipLength
        if [ $ipLength -gt 1 ]; then
                echo "Ethernet Running, exiting..."
                exit 3
        else
                modem=$( /etc/udev/nvtl_modem.sh 2>&1 )
                echo "$modem"
                modemLength="${#modem}"
                echo $modemLength
                if [ "$modemLength" = "0" ]; then
                        echo "USB Cell Modem Connected"
                        diffcheck=$( diff /etc/default/wvdial.conf /etc/wvdial.conf 2>&1 )
                        echo "$diffcheck"
                        outLength="${#diffcheck}"
                        echo "$outLength"
                        if [ "$outLength" = "0" ]; then
                                echo "run wvdial"
                        else
                                echo "copy wvdial.conf"
                                cp /etc/default/wvdial.conf /etc/wvdial.conf
                        fi
                        wvdial &
                else
                        echo "No USB Cell Modem Connected"
                        exit 3
                fi
        fi
        
        
}

#
# Function that stops the daemon/service
#
do_stop()
{
        pkill wvdial
}

do_status()
{
        ipAddress=`/sbin/ifconfig ppp0 | grep "inet addr" | cut -d":" -f2 | cut -d" " -f1`
        echo "$ipAddress"
        ipLength=`expr length "$ipAddress"`
        echo $ipLength
        if [ $ipLength -gt 1 ]; then
                echo "USB Cell Modem Up and Running"
        else
                echo "USB Cell Modem Not Up"
        fi
}


case "$1" in
  start)
        do_start
        ;;
  stop)
        do_stop
        ;;
  status)
        do_status
        ;;
  *)
        echo "Usage: $SCRIPTNAME {start|stop|status}" >&2
        exit 3
        ;;
esac


:

I also copy wvdial.conf into /etc/default in case it gets corrupted or changed.

I then run the following command:

insserv cellmodem.sh

and that sets it up.

The cell modem and ethernet don't like working at the same time so the script checks to see if eth0 has an IP address and if so it doesn't setup the cell modem.  Otherwise it does setup the cell modem.  It still needs some work but a good initial run.

Side note: I notice that on occasion the cell modem doesn't turn on even though your plug it into the BBB.  I power down and try again and eventually the LED on the cell modem will turn on and then everything powers up.

Monday, January 27, 2014

Getting MPLAB X working with OS X Maverick

I just updated to Maverick and noticed that MPLAB did not work.  I had observed others update and have the similar issues.  Before the update I had downloaded and installed the latest version of MPLAB X from the  Microchip website.  After the update, MPLAB wouldn't even start because I needed Java.  I downloaded the latest version of Java and still nothing, but I recalled in the microchip forums the following post (http://www.microchip.com/forums/m774977.aspx).  The post points you to apple support (http://support.apple.com/kb/DL1572) where you can download an older version of Java that works with MPLAB X.  I downloaded and installed this version of Java and now MPLAB X would start up but it couldn't see any of my programmers (ICD 3 or PICkit3).  So I uninstalled MPLAB X and then reinstalled it and magically my programmers reappeared.

Thursday, January 16, 2014

Making Debian Packages the Quick and Dirty Way

I love Debian. Which is like saying "I love New York". So let me be more specific. I don't actually care for Debian docs (great example of more is less). Or the overtly zealous worship of the Debian Ideals (IceWeasel, seriously?). Or the Debian irc channel ("go away, read the docs, leave us alone"). 

But I do really like the Debian package management system. Building an (embedded) product based on a Debian system, means you can make your own software modular, and installed/upgraded using Debian packages. When working with other developers, this means that you can use a local repository to synchronize your work. Which is a lot better than "hey, let me Skype you my modified version of /etc/network/interfaces." So much better to put that in a package that can be loaded by everyone, and when you update it, everyone can grab the updates.

But making Debian packages is... involved. There are guidelines, and makefiles, and multiple tools, etc. But if you just want a simple binary package owned and managed just by you, that just puts files in places and runs scripts, there are easier ways.

A Debian package is just an ar package of three files: debian-binary, control.tar.gz, and data.tar.gz. debian-binary is a fixed file. Package metadata goes in control.tar.gz and your new files go in data.tar.gz. So let's walk through making a package that does something simple (and pretty much pointless, but hey, it's an example). Our simpledebpackage will add a newSingleFile to the file system and then make a simple edit to it. To make sure I'm not using a bunch of Debian specific tooling, I'm actually going to do it from the command line in OSX.
$ cd ~
$ mkdir simpledebpackage # our working directory, can be named whatever you want
$ cd simpledebpackage/
Now let's create the canned debian-binary file:
$ echo "2.0" > debian-binary
Let's do the new file next:
$ mkdir ROOT # this represents the root of the file system when installing
$ cd ROOT # you can name it whatever you want
$ mkdir -p usr/local # the path where newSingleFile will go on the target system
$ echo "What is the Answer?" > usr/local/newSingleFile # create a simple newSingleFile
$ tar -cvzf ../data.tar.gz * # archive all the files you want to add to the data.tar.gz file
$ cd ..
That was easy. Now for the package metadata:
$ mkdir DEBIAN # directory put all of our meta files
$ cd DEBIAN #again, the name isn't important
Use your favorite editor (mine is vim) to add a file named control (this name is important):
$ cat control
Package: simpledebpackage
Version: 1.0.0
Architecture: all
Maintainer: me@somewhere.mail
Description: The simplest package that possibly could
The control file defines the package metadata. Those are the 5 required fields. You can add more. The manual describes all of the fields in section 5.3.

Now build a simple shell script named postinst (this name is important too):
$ cat postinst
#!/bin/sh
echo "Duh: 42" >> /usr/local/newSingleFile
postinst is an example of a maintainer script. There are others like postrm, preinst, etc. What they are and when they fire is shown in graphical glory over at the Debian Wiki.

Now we ball these up similar to how we did the data.tar.gz one:
$ tar -cvzf ../control.tar.gz *
a control
a postinst
$ cd ..
The only thing that remains to be done is to ball the 3 files up in an archive file:
$ ar r simpledebpackage_1.0.0.deb debian-binary control.tar.gz data.tar.gz
One word of warning. Debian parses fields from filenames based on the underscore character. So, don't use it in your package name. Also, capital letters will cause warnings as well.

To test your package just run

        $dpkg -i simpledebpackage_1.0.0.deb

Tuesday, January 14, 2014

Compiling Adafruit Library for Python3

Wanted to compile the Adafruit BeagleBone Black GPIO library for python 3.  To accomplish this I did the following:

git clone git://github.com/adafruit/adafruit-beaglebone-io-python.git
cd adafruit-beaglebone-io-python
Now we need to change the setup.py script to be python3 compatible (I got errors with the SPI portion so I commented it out - don't need it for my purposes):

# Some Angstrom images are missing the py_compile module; get it if not
# present:
# Fix credit:https://github.com/alexanderhiam/PyBBIO/blob/master/setup.py
import random, os
python_lib_path = random.__file__.split('random')[0]
print(python_lib_path)
if not os.path.exists(python_lib_path + 'py_compile.py'):
  print("py_compile module missing; installing to %spy_compile.py", python_lib_path)
  import urllib2
  url = "http://hg.python.org/cpython/raw-file/4ebe1ede981e/Lib/py_compile.py"
  py_compile = urllib2.urlopen(url)
  with open(python_lib_path+'py_compile.py', 'w') as f:
    f.write(py_compile.read())
  print("testing py_compile...")
  try:
    import py_compile
    print("py_compile installed successfully")
  except Exceptions as e:
    print("*py_compile install failed, could not import")
    print("*Exception raised:")
    raise e
try:
    from overlays import builder
    builder.compile()
    builder.copy()
except:
    pass
import distribute_setup
distribute_setup.use_setuptools()
from setuptools import setup, Extension, find_packages
classifiers = ['Development Status :: 3 - Alpha',
               'Operating System :: POSIX :: Linux',
               'License :: OSI Approved :: MIT License',
               'Intended Audience :: Developers',
               'Programming Language :: Python :: 2.6',
               'Programming Language :: Python :: 2.7',
               'Programming Language :: Python :: 3',
               'Topic :: Software Development',
               'Topic :: Home Automation',
               'Topic :: System :: Hardware']
setup(name             = 'Adafruit_BBIO',
      version          = '0.0.19',
      author           = 'Justin Cooper',
      author_email     = 'justin@adafruit.com',
      description      = 'A module to control BeagleBone IO channels',
      long_description = open('README.rst').read() + open('CHANGELOG.rst').read(),
      license          = 'MIT',
      keywords         = 'Adafruit BeagleBone IO GPIO PWM ADC',
      url              = 'https://github.com/adafruit/adafruit-beaglebone-io-python/',
      classifiers      = classifiers,
      packages         = find_packages(),
      py_modules       = ['Adafruit_I2C'],
      ext_modules      = [Extension('Adafruit_BBIO.GPIO', ['source/py_gpio.c', 'source/event_gpio.c', 'source/constants.c', 'source/common.c']),
                          Extension('Adafruit_BBIO.PWM', ['source/py_pwm.c', 'source/c_pwm.c', 'source/constants.c', 'source/common.c']),
                          Extension('Adafruit_BBIO.ADC', ['source/py_adc.c', 'source/c_adc.c', 'source/constants.c', 'source/common.c']),
#                          Extension('Adafruit_BBIO.SPI', ['source/spimodule.c', 'source/constants.c', 'source/common.c']),
                          Extension('Adafruit_BBIO.UART', ['source/py_uart.c', 'source/c_uart.c', 'source/constants.c', 'source/common.c'])])



I saved my changes as setup3.py.  Make sure you have python3 and python3-dev installed (apt-get install).

When I ran python3 setup3.py install the first time I got an error:

source/common.c: In function ‘load_device_tree’:
source/common.c:360:5: error: format not a string literal and no format arguments [-Werror=format-security]

So I changed line 360 to the following:

fprintf(file,"%s", name);

and then it compiled (I originally tried it with SPI included and got an error thus why I commented it out above).





Monday, January 13, 2014

reprepro and nginx


Experimenting with reprepro and nginx as a private package server (blog I followed):

apt-get install reprepro
mkdir -p /srv/reprepro/debian/{conf,dists,incoming,indices,logs,pool,project,tmp}
sudo chown -R `whoami` .

then create distributions file in conf:


Origin: Your Name
Label: Your repository
nameCodename: thunder
Architectures: armhf source
Components: main
Description: Description of repository you are creating

to add a package:

reprepro -S admin -P extra -b /srv/reprepro/debian includedeb thunder myapp_1.0_i386.deb

To make it accessible you have to setup a server.  Using nginx (apt-get install if necessary), in my case it was already being used by a server so I created a new server  (/etc/nginx/sites-available/reprepro.conf) containing the following:


server {
  listen 8080;
  server_name ipaddress;

  access_log /var/log/nginx/reprepro-access.log;
  error_log /var/log/nginx/reprepro-error.log;

  location / {
    root /srv/reprepro;
    index index.html;
  }

  location ~ /(.*)/conf {
    deny all;
  }

  location ~ /(.*)/db {
    deny all;
  }
}

I then place a virtual link in /etc/nginx/sites-enabled (sudo ln -s ../sites-available/reprepro.conf .) and then restart nginx (sudo service nginx reload).

Then to access the server I add the following to /etc/apt/sources.list:

deb http://ipaddress:port/debian thunder main

then apt-get update

now you should be able to install your package.

apt-get install myapp


Friday, January 10, 2014

(Code) Comments Lie

I have a young friend, who has entered the halls of academia to learn how to program. He's expressed frustration that the teachers spend what seems a disproportionate amount of time obsessing about code comments.

I come from the eXtreme Programming school which took a dim (and controversial) view on commenting for the sake of commenting, or often even, commenting for much of any reason at all. I stumbled on a great one just now. I'm still chuckling.

In a relatively small code base of some embedded code I have a function that looks like:

void setupPrintf(void)
{
    // set PORTC0 for UART
    PR.PRPC &= ~PR_USART0_bm; // enable it
    PORTC.PIN2CTRL = PORT_OPC_TOTEM_gc;
    PORTC.DIRCLR = PIN2_bm;
    PORTC.PIN3CTRL = PORT_OPC_TOTEM_gc;
    PORTC.DIRSET = PIN3_bm;
    PORTC.OUTSET = PIN3_bm; // Drive Pin3 High
    USARTC0.CTRLB |= USART_TXEN_bm;  // enable transmission
//  USARTC0.CTRLB |= USART_RXEN_bm; // no need for reception
//  USARTC0.CTRLA = USART_RXCINTLVL_LO_gc; // no need for reception
    USARTC0.CTRLC = USART_CHSIZE_8BIT_gc | USART_PMODE_DISABLED_gc;// 8N1
    USARTC0.BAUDCTRLA = 123; // 230400
    USARTC0.BAUDCTRLB = (-4 << USART_BSCALE0_bp);
    stdout = &UART_STDOUT;
    backgroundWorkAdd(&PrintTask);
}

Some gnarly C code filled with lots of lovely spec sheet abreviations. We're not a big team, just two of us. We've had some changes lately in our hardware and are doing some rewriting to adapt. Amongst others, we wrote the following code (in a separate function in another file):

    ....
    PR.PRPC &= ~PR_USART0_bm; // make sure it is enabled
    USARTC0.CTRLB |= USART_RXEN_bm; // no need for reception
    USARTC0.CTRLA |= USART_RXCINTLVL_LO_gc; // lo level interrupt
    USARTC0.CTRLC = USART_CHSIZE_8BIT_gc | USART_PMODE_DISABLED_gc;// 8N1
    USARTC0.BAUDCTRLA = 123; // 230400
    USARTC0.BAUDCTRLB = (-4 << USART_BSCALE0_bp);
    ....


Do you see it? I didn't either at first. Because I don't pay much to comments usually. The amusing line is the second line in the new code:

    USARTC0.CTRLB |= USART_RXEN_bm; // no need for reception

That line was copy/pasted from the original body. The comment "no need for reception now" was actually a reference to the fact that the whole line was commented out, not what the code does. Because the code does the exact opposite. So the new copy, no longer commented out, contains a single line of code where the code does the exact opposite of what the comment says it does.

Less is More. It would have been better if I had just removed the 2 lines in the first place many moons ago. And you should never copy/paste comments. Period.