Use Arduino and two hobby servos to control physical servo gauges for cpu activity, memory usage, bandwidth, and more. The script uses the python psutil and pyserial modules. The psutil module provides an interface for retrieving information on all running processes and system utilization (CPU, disk, memory, network) providing service similar to command line tools such as ps, top, iostat, and netstat. The servo control portion of the project is based on Arduino-Python 4-Axis Servo Controlby Brian Wendt, and the Arduino sketch is essentially unmodified from the SerialServoControl Sketch on Sparkfun.
Connect the red, power lines of the servos to +5v, the black ground lines to GND, and the yellow signal lines to the desired output pins, 5 and 6 in the example (others can be used, but must be PWM capable
You can download my cheesy gauge overlay from here:
Print it out, cut out the gauges, and poke a hole in the lower center of the gauge. Remove the servo horn, slide the shaft through the hole in the gauge printout, and reconnect the servo horn on top of it.
The first step is to install the python psutil and pyserial modules. The easiest way to install it is using the python pip package manager. If you don’t have it installed already, you can install it using apt-get:
sudo apt-get install python-pip
Then install the psutil and pyserial modules:
sudo pip install psutil pyserial
Next, flash the sketch to the Arduino board. You can download it or copy and paste into the Arduino IDE.
Then download or copy and paste the Python script:
That’s it! To run the script:
Note:If you receive this error:
raise SerialException(“could not open port %s: %s” % (self._port, msg)) serial.serialutil.SerialException: could not open port /dev/ttyUSB0: [Errno 13] Permission denied: ‘/dev/ttyUSB0′
The problem is the default permissions of the /dev/ttyUSB0 (or /dev/ttyACM0) device. This can be fixed by running the command:
sudo chmod 777 /dev/ttyUSB0
Turn your Arduino UNO into a USB HID keyboard, and make buttons that do whatever you want. Make it a useful tool, with new buttons for Cut/Copy/Paste or Volume+/Volume-/Mute, or annoy your friends and colleagues by setting the keyboard to perform random keypress after random delays!
The USB HID keyboard conforms to the standard USB specification, so is functional on all modern operating systems. All this is made possible by the use of the Arduino Device Firmware Update (DFU) function.
Arduino Device Firmware Update (DFU)
The Atmega8U2 chip on the Arduino UNO can be programmed directly using the special USB protocol called Device Firmware Update (DFU). This is completely independant of the ‘normal’ method of flashing sketches to the board using the Arduino IDE.
This process is normally used to update the firmware to a more recent version, as explained in the offical Arduino guide, Updating the Atmega8U2 on an Uno or Mega2560 using DFU. Note: If your board is NOT an Arduino UNO SMD you’ll need to solder a 10k resistor (Brown-black-orange) at the back of your board as shown on the Arduino site.
However, in addition to the ability to flash standard USB Serial firmwares, we can also flash alternative firmwares as well. This allows the device to be recognized as many other device types, including keyboard, mouse, joystick, midi device, etc. This is made possible in part to the wonderful open source LUFA (Lightweight USB Framework for AVRs) USB stack, and keyboard HID firmware from Darran.
In this demonstration, we will flash generic USB HID keyboard firmware. The USB HID protocol provides manufactures the generic specifications to interact with nearly every operating system in existence. For more info, check out the USB HID Spec sheet.
Before you start, install the required packages. On Ubuntu and Debain systems, in a terminal run:
sudo apt-get install dfu-programmer dfu-util
For Windows and Mac instructions to install the dfu-programmer tool, consult the official Arduino DFU documentation.
Then download these two firmware files:
The first step is to make sure you are able to flash the standard arduino firmware. This will confirm that the programmer and the environment are both functional. NOTE: There is no chance of ‘bricking’ the device using this method. The Arduino bootloader firmware can always be updated using the DFU protocol!
sudo dfu-programmer at90usb82 erase sudo dfu-programmer at90usb82 flash --debug 1 Arduino-usbserial.hex sudo dfu-programmer at90usb82 reset
Plug cycle the Arduino, then open the Arduino IDE and ensure that you can still upload a sketch. Assuming everything flashes normally, we can move forward with flashing the HID keyboard firmware.
sudo dfu-programmer at90usb82 erase sudo dfu-programmer at90usb82 flash --debug 1 Arduino-keyboard-0.3.hex sudo dfu-programmer at90usb82 reset
NOTE: The Arduino can only be flashed with skectches through the Adruino IDE if the Arduino-usbserial.hex bootloader is active. So, to develop a USB HID device, the process becomes:
Flash Arduino-usbserial.hex bootloader with dfu-programmer (erase/flash/reset)
Plug cycle the Arduino
Flash firmware sketch using Arduino IDE
Plug cycle the Arduino
Flash Arduino-keyboard-0.3.hex bootloader with dfu-programmer (erase/flash/reset)
Test and repeat
Now that you understand how the process works, you can try out some of these keyboard samples. The easiest example is the random keypress with random delays, since it doesn’t require any components connected to the Arduino.
Random Key/Random Delay
The following two examples both use three buttons connected to the Arduino. The code can easily be changed to make the buttons perform other actions, by consulting the mapping tables in the USB HID documentation. Here is a diagram of the circuit, (created with Fritzing):
This tutorial will demonstrate how to cross compile the kernel for the Raspberry Pi on Ubuntu 12.04 LTS. The kernel is functional with both the Debian and Arch Linux Raspberry Pi images. First, install the package dependencies, git and the cross-compilation toolchain:
sudo apt-get install git-core gcc-4.6-arm-linux-gnueabi
Create a symlink for the cross compiler:
sudo ln -s /usr/bin/arm-linux-gnueabi-gcc-4.6 /usr/bin/arm-linux-gnueabi-gcc
Make a directory for the sources and tools, then clone them with git:
git clone https://github.com/raspberrypi/tools.git
git clone https://github.com/raspberrypi/linux.git
Generate the .config file from the pre-packaged raspberry pi one:
make ARCH=arm CROSS_COMPILE=/usr/bin/arm-linux-gnueabi- bcmrpi_cutdown_defconfig
If you want to make changes to the configuration, run make menuconfig (optional):
make ARCH=arm CROSS_COMPILE=/usr/bin/arm-linux-gnueabi- menuconfig
Once you have made the desired changes, save and exit the menuconfig screen. Now we are ready to start the build. You can speed up the compilation process by enabling parallel make with the -j flag. The recommended use is ‘processor cores + 1′, e.g. 5 if you have a quad core processor:
make ARCH=arm CROSS_COMPILE=/usr/bin/arm-linux-gnueabi- -k -j5
Assuming the compilation was sucessful, create a directory for the modules:
Then compile and ‘install’ the loadable modules to the temp directory:
make modules_install ARCH=arm CROSS_COMPILE=/usr/bin/arm-linux-gnueabi- INSTALL_MOD_PATH=../modules/
Now we need to use imagetool-uncompressed.py from the tools repo to get the kernel ready for the Pi.
This creates a kernel.img in the current directory. Plug in the SD card of the existing Debian image that you wish to install the new kernel on. Delete the existing kernel.img and replace it with the new one, substituting “boot-partition-uuid” with the identifier of the partion as it is mounted in Ubuntu.
sudo rm /media/boot-partition-uuid/kernel.img
sudo mv kernel.img /media/boot-partition-uuid/
Next, remove the existing /lib/modules and lib/firmware directories, substituting “rootfs-partition-uuid” with the identifier of the root filesystem partion mounted in Ubuntu.
sudo rm -rf /media/rootfs-partition-uuid/lib/modules/
sudo rm -rf /media/rootfs-partition-uuid/lib/firmware/
Go to the destination directory of the previous make modules_install, and copy the new modules and firmware in their place:
sudo cp -a lib/modules/ /media/rootfs-partition-uuid/lib/
sudo cp -a lib/firmware/ /media/rootfs-partition-uuid/lib/
That’s it! Exject the SD card, and boot the new kernel on the Raspberry Pi!
This tutorial will demonstrate how to setup and connect to a Raspberry Pi over VNC from Ubuntu. This process is easier if you have a display connected to the Raspberry Pi, but will also show the steps to connect with only Ethernet and power connected. It assumes you have Debian for Raspberry Pi installed on an SD card. If not, see RPi Easy SD card setup
Getting the IP address of the Raspberry Pi
The first step is to locate the Raspberry Pi on your network. If you have access to a display for your Raspberry Pi, this task is simple, in a terminal simply type:
All the network interface configurations will be displayed, including the IP address. However, if you don’t have a display for your Raspberry Pi, this isn’t an option. For this task, we can use the Linux nmap (Network Mapper) utility.
sudo apt-get install nmap
Then run a scan on your local network. Be change to the specifics of your own network.
nmap -sV -p 22 192.168.0.1-255
The results will display every machine that could be identified on port 22. The Raspberry Pi (running Debian) looks something like this:
Nmap scan report for 192.168.0.112
Host is up (0.033s latency).
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 5.5p1 Debian 6+squeeze2 (protocol 2.0)
Service Info: OS: Linux
Connecting over SSH
So we know that the Raspberry Pi has IP address: 192.168.0.112. Now we can ssh to it:
And you should receive a message like this:
The authenticity of host ’192.168.0.112 (192.168.0.112)’ can’t be established.
RSA key fingerprint is xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx.
Are you sure you want to continue connecting (yes/no)?
Type yes at the prompt, then enter the password for the user pi, ‘raspberry’ by default. You should get a prompt that looks like this:
Now that we have logged in to the Raspberry Pi, we can setup VNC for remote access. First we need to install the VNC server:
sudo apt-get install tightvncserver
Next, start the VNC server on the Raspberry Pi. Adjust the geometry paramater to your desired display size.
vncserver :1 -geometry 1024x600 -depth 16 -pixelformat rgb565
You will be prompted to create a password for VNC login. Once you do, you should see a line looking something like this:
New ‘X’ desktop is raspberrypi:1
Now, we can finally connect to the Pi with VNC. Back on the Ubuntu machine, install the VNC viewer client:
sudo apt-get install xtightvncviewer
Then connect to the running VNC server:
To stop the VNC viewer, just close the application. To stop the VNC server, issue the following command (on the Raspberry Pi):
vncserver -kill :1
The following are some typical errors. Some of these may be caught at compilation or link time, and some may only cause problems when you call insmod with the module.
- division by zero
- dereferencing a null pointer
- returning no value or a value other than zero from init_mod
- calling a C library routine (e.g., malloc() or printf()) from inside a kernel module
Beware that errors in the kernel sometimes have no immediate visible effect, but they may have a delayed effect that is disastrous. This is generally the case if you write garbage into random locations of kernel memory. The location you corrupt may not be referenced to a while. It will be referenced later, and then the effect will occur. Therefore, you cannot assume that the thing you did most recently is necessarily the cause of a crash.
As a consequence, during actual kernel development, one needs to test new kernel code extensively, letting the system run long enough (and with enough other activities going on) to give you confidence that the new code has no harmful side-effects. When you are debugging your own code, if you have tested some code that seems to have gone badly wrong, but not badly enough to crash the system (yet), you may want to reboot the system before testing your revised code. I have seen cases where a system crashed while executing the corrected code, but the crash was because of the delayed effect of damage that had been done by the previously executed (bad) version of the code.
Kernel Debugging Tips
Here are a few tips to ease kernel development and save some time on repeated reboots.
Make Grub Visible
sudo vim /etc/default/grub
Change this line:
Then run grub update:
Make Verbose Boot:
sudo vim /etc/default/grub
Change this line:
Also change this line:
Then run grub update:
Text Based Login:
sudo vim /etc/default/grub
Change this line:
Then run grub update:
Remove Unnecessary Services (while debugging):
sudo apt-get remove apparmor
This is a significant savings as far as boot time is concerned. On my machine, the removal of apparmor reduced the boot-up time by over 10 seconds.
This tutorial will outline the process to compile your own kernel for Ubuntu. It will demonstrate both the traditional process using ‘make’ and ‘make install’ as well as the Debian method, using ‘make-dpkg’. This is the detailed version of this tutorial, see Compile Linux Kernel on Ubuntu 12.04 LTS for the quick overview. In any case, we begin by installing some dependencies:
sudo apt-get install git-core libncurses5 libncurses5-dev libelf-dev asciidoc binutils-dev linux-source qt3-dev-tools libqt3-mt-dev libncurses5 libncurses5-dev fakeroot build-essential crash kexec-tools makedumpfile kernel-wedge kernel-package
Note: qt3-dev-tools and libqt3-mt-dev is necessary if you plan to use ‘make xconfig’ and libncurses5 and libncurses5-dev if you plan to use ‘make menuconfig’. Next, copy the kernel sources with wget:
Extract the archive and change into the kernel directory:
tar -xjvf linux-3.2.17.tar.bz2 cd linux-3.2.17/
Now you are in the top directory of a kernel source tree. The kernel comes in a default configuration, determined by the people who put together the kernel source code distribution. It will include support for nearly everything, since it is intended for general use, and is huge. In this form it will take a very long time to compile and a long time to load. So, before building the kernel, you must configure it. If you wish to re-use the configuration of your currently-running kernel, start by copying the current config contained in /boot:
cp -vi /boot/config-`uname -r` .config
Parse the .config file using make with the oldconfig flag. If there are new options available in the downloaded kernel tree, you may be prompted to make a selection to include them or not. If unsure, press enter to accept the defaults.
Since the 2.6.32 kernel, a new feature allows you to update the configuration to only compile modules that are actually used in your system. As above, make selections if prompted, otherwise hit enter for the defaults.
The next step is to configure the kernel to your needs. You can configure the build with ncurses using the ‘menuconfig’ flag:
or, using a GUI with the ‘xconfig’ flag:
In either case, you will be presented with a series of menus, from which you will choose the options you want to include. For most options you have three choices: (blank) leave it out; (M) compile it as a module, which will only be loaded if the feature is needed; (*) compile it into monolithically into the kernel, so it will always be there from the time the kernel first loads.
There are several things you might want to accomplish with your reconfiguration:
- Reduce the size of the kernel, by leaving out unnecessary components. This is helpful for kernel development. A small kernel will take a lot less time to compile and less time to load. It will also leave more memory for you to use, resulting in less page swapping and faster compilations.
- Retain the modules necessary to use the hardware installed on your system. To do this without including just about everything conceivable, you need figure out what hardware is installed on your system. You can find out about that in several ways.
Before you go too far, use the “General Setup” menu and the “Local version” and “Automatically append version info” options to add a suffix to the name of your kernel, so that you can distinguish it from the “vanilla” one. You may want to vary the local version string, for different configurations that you try, to distinguish them also.
Assuming you have a running Linux system with a working kernel, there are several places you can look for information about what devices you have, and what drivers are running.
- Look at the system log file, /var/log/messages or use the command dmesg to see the messages printed out by the device drivers as they came up.
- Use the command lspci -vv to list out the hardware devices that use the PCI bus.
- Use the command lsub -vv to list out the hardware devices that use the USB.
- Use the command lsmod to see which kernel modules are in use.
- Look at /proc/modules to see another view of the modules that are in use.
- Look at /proc/devices to see devices the system has recognized.
- Look at /proc/cpuinfo to see what kind of CPU you have.
- Open up the computer’s case and read the labels on the components.
- Check the hardware documentation for your system. If you know the motherboard, you should be able to look up the manual, which will tell you about the on-board devices.
Using the available information and common sense, select a reasonable set of kernel configuration options. Along the way, read through the on-line help descriptions (for at least all the top-level menu options) so that you become familiar with the range of drivers and software components in the Linux kernel.
Before exiting the final menu level and saving the configuration, it is a good idea to save it to a named file, using the “Save Configuration to an Alternate File” option. By saving different configurations under different names you can reload a configuration without going through all the menu options again. Alternatively, you can backup the file (which is named .config manually, by making a copy with an appropriate name.
One way to reduce frustration in the kernel trimming process (which involves quite a bit of guesswork, trial, and error) is to start with a kernel that works, trim just a little at a time, and test at each stage, saving copies of the .config file along the way so that you can back up when you run into trouble. However, the first few steps of this process will take a long time since you will be compiling a kernel with huge number of modules, nearly all of which you do not need. So, you may be tempted to try eliminating a large number of options from the start
Now we are ready to start the build. You can speed up the compilation process by enabling parallel make with the -j flag. The recommended use is ‘processor cores + 1′, e.g. 5 if you have a quad core processor:
This will compile the kernel and create a compressed binary image of the kernel. After the first step, the kernel image can be found at arch/i386/boot/bzImage (for a x86 based processor). Once the initial compilation has completed, install the dynamically loadable kernel modules:
sudo make modules_install
The modules are installed in a subdirectory of “/lib/modules”, named after the kernel version. The resulting modules have the suffix “.ko”. For example, if you chose to compile the network device driver for the Realtek 8139 card as a module, there will be a kernel module name 8139too.ko. The third command is OS specific and will copy the new kernel into the directory “/boot” and update the Grub bootstrap loader configuration file “/boot/grub/grub.cfg” to include a line for the new kernel.
Finally, install the kernel:
sudo make install
This command performs many operations behind the scenes. Examine the /etc/grub.d/ directory structure before and after you run the above commands to see the changes. Also look in the /boot/grub/grub.cfg file for your kernel entry.
The OS specific make install, Ubuntu in this case, also creates an initrd image in the /boot directory. If you compiled the needed drives into the kernel then you will not need this ramdisk file to aid in booting. For extra credit remove the created initrd from the /boot/ directory as well as the references in /etc/grub.d/*.
If there are error messages from any of the make stages, you may be able to solve them by going back and playing with the configuration options. some options require other options or cannot be used in conjunction with some other options. These dependencies and conflicts may not all be accounted-for in the configuration script. If you run into this sort of problem, you are reduced to guesswork based on the compilation or linkage error messages. For example, if the linker complains about a missing definition of some symbol in some module, you might either turn on an option that seems likely to provide a definition for the missing symbol, or turn off the option that made reference to the symbol.
Reboot the system, selecting your new kernel from the boot loader menu. Watch the messages. See if it works. If it does not, reboot with the old kernel, try to fix what went wrong, and repeat until you have a working new kernel
Instead of the compilation process of above, you can alternatively compile the kernel as installable .deb packages. This improves the portability of the kernel, since installation on a different machine is as simple as installing the packages. Rather than using ‘make’ and ‘make install’, we use ‘make-kpkg’:
fakeroot make-kpkg – -initrd – -append-to-version=-some-string-here kernel-image kernel-headers
Unlike above, you cannot enable parallel compilation with make-kpkg using the -j flag. Instead, define the CONCURRENCY_LEVEL environment variable.
Once the compilation has completed, you can install the kernel and kernel headers using dpkg:
sudo dpkg -i linux-image-3.2.14-mm_3.2.14-mm-10.00.Custom_amd64.deb
sudo dpkg -i linux-headers-3.2.14-mm_3.2.14-mm-10.00.Custom_amd64.deb