Learn

Praface

These are some lessons, projects, and code we have made and decided to share with the world. We like to document our work so we can come back to it later, but hopefully others find it useful too! If you would like to see some other topics, feel free to contact us.

Using the Website

Below is a tree of all topics, lessons, and content. You can also print the whole thing at once!

There is also a tag cloud over at the right.

Arduino

Preface

Arduino is an awesome way to get into robotics. It is a very easy to use microcontroller that you program in C/C++. It does analog digital on/off input and output, reading of voltages, anolog output by Pulse Width Modulation (PWM) which is useful for hooking up motors, serial communication which is useful for communicating with sensors and other external devices.

A simple Arduino program example is blinking an LED. The code looks like this:

int led = 13; // Pin 13 has an LED connected on most Arduino boards.

void setup() {               // the setup routine runs once when you press reset:
pinMode(led, OUTPUT);      // initialize the digital pin as an output.
}

void loop() {                // the loop routine runs over and over again forever:
digitalWrite(led, HIGH);   // turn the LED on (HIGH is the voltage level)
delay(1000);               // wait for a second
digitalWrite(led, LOW);    // turn the LED off by making the voltage LOW
delay(1000);               // wait for a second
}


Not too hard, right? We have lots of tutorials on how to do more advanced things with your Arduino.

Pulse Width Modulation with analogWrite

Pulse Width Modulation (PWM) is used because a microcontroller cannot easily send a specific voltages. It really can only turn a switch on and off. To be able to send a ratio of the current voltage, something like a variable resistor would need to be digitally controlled, but we don't have that. Instead, what PWM does is essentially flip the switch really really fast. That way the average voltage can be varied by leaving the switch on for longer or shorter than it is off.

So, the average voltage is the percent duty cycle, multiplied by the "on" voltage.

Arduino Example

To get 2.5 average volts, just use a 50% duty cycle, since the Arduino outputs 5V normally.

However, the PWM function in arduino does not take duty cycle as a percentage. It takes it as a whole number out of 255. So, a 100% duty cycle would be 255. The 50% duty cycle would be 0.50 * 255 = 127.

Be sure to use a pin on the Arduino that has a ~ next to it, which represents that the pin can do PWM. Not all pins can. On an Arduino Uno, the available pins are 3, 5, 6, 9, 10, and 11. In this example, we will use 5 for no particular reason.

The resulting code to output 2.5 average volts will look like this:

analogWrite( 5, 127 ); // pin 5, half of 255 for 50%

Introduction

Reading numbers from serial on an Arduino is needed surprisingly commonly. Exactly what is happening might be kind of hard to figure out.

Serial

Serial communication is digital, which means all data is transmitted in 1's and 0's. Typically, serial communication is done using ASCII letters. This means that, to send a number to the Arduino, the data sent is not the binary version of the number in base 2 (as an integer), but instead a sequence of characters for each digit in base 10 (which is human-readable). It is not an efficient use of bandwidth, but bandwidth is not usually a problem with Arduinos connect by USB.

Arduino Code

char commandLetter;  // the delineator / command chooser
char numStr[4];      // the number characters and null
long speed;          // the number stored as a long integer

void serialEvent() {
// Parse the string input once enough characters are available
if(Serial.available() >= 4) {

//dump the buffer if the first character was not a letter
if ( ! isalpha( commandLetter ) {
// dump until a letter is found or nothing remains
while(( ! isalpha( Serial.peak() ) && Serial.available()) {
Serial.read(); // throw out the letter
}

//not enough letters left, quit
if ( Serial.available() < 3 ) {
return;
}
}

// read the characters from the buffer into a character array
for( int i = 0; i < 3; ++i ) {
}

//terminate the string with a null prevents atol reading too far
numStr[i] = '\0';

//read character array until non-number, convert to long int
speed = atol(numStr);
Serial.println(speed);
}
}


Code Explanation

serialEvent

serialEvent is a function that is called by Arduino before each loop. So, you can separate out your serial handling from the rest of your code. You could also put the contents of this function in the loop() function and it would be similar.

Fixed-Width

Commands need to be delineated in some way. Fixed-width commands are convenient on Arduino because the Serial.available function tells you how many characters are waiting. It is also possible to delineate by special characters. An extremely common and simple version of this is a Comma Separated Value file. However, since it is simplest to use C strings, the character arrays which the serial is read into is necessarily fixed-width anyway. To get around this issue, a vector or linked list could be used, so the serial string can dynamically grow and shrink.

Command Differentiation

In many cases, a robot takes multiple kinds of inputs. For example, there might be multiple speeds, or a direction, or some kind of trigger. Prefixing each command with a unique letter can make it easy to differentiate what the following string is supposed to do.

C Strings

C strings are arrays of char data types. They must be terminated by a NULL character '\textbackslash 0'. Without the NULL character at the end, there is no way for any function to know how long the string is. For example, a print function would print the string and then a bunch of garbage characters until it gets to a NULL or the end of the memory available. In this case, it's less likely for that to happen since we are only using atol, which will only read until there is a non-numeric character. A non-numeric byte is more likely to randomly be at the end of the string than a NULL character.

 Decimal Character 48 '0' 49 '1' 50 '2' 51 '3' 52 '4' 53 '5' 54 '6' 55 '7' 56 '8' 57 '9'

Char to Integer

Converting a single character to a number takes advantage of how characters are stored, which is typically in a format called ASCII. Think of a char of ASCII like an integer data type. Except that when printed, it is not a decimal number. The number in the int is translated into a letter on the screen according to a table. For example, the decimal number 97 is translated into the letter 'a'. Each letter is really stored as a 'number'. I'm showing it as a decimal (base 10) number, but it is really stored in binary (base 2). The C++ compile takes care of translating our base 10 decimal numbers into base 2 binary.

Here is how to take advantage of this:

int number = (int)charInput - (int)48;// or:int number = charInput - '0';

Since ASCII stores the letters sequentially, starting at 0, just subtract the value where 0 begins from each of the characters to convert it to its numeric form. This works regardless of the base of the character storage. So, it converts the ASCII character representing the number in base 10 into an integer in base 2.

Char Array (C-string) to Long Integer

Now, each of the letters from right to left need to be multiplied by a power of 10. Here is the basic idea of what atol does:

char charArray[5] = "5432"; // double quotes adds the \0 at the end

long longnum = 0;  //the converted number
int index = 0;     //the current place in the array

//find the end of the string - when character is not a number
while ( isdigit( charArray[idx] ) ) {
++idx;
}

//begin base multiplication and number conversion
while( idx >= 0 ) {
//convert digit character to a long
long currentDigit = (long) charArray[idx] - (long)48

currentDigit *= exponent; //number multiplied by 10^(len-idx)
exponent *= 10; // next number to left is another power of ten

longnum += currentDigit;
--idx;
}


Serial Commands

Introduction

Serial communication through USB can be used to communicate between a host computer (like a laptop, or Raspberry Pi), and an Arduino. Doing so allows:

• Use of the faster hardware of the host computer for calculations
• Synchronization of multiple Arduinos
• Use of other information provided by the host computer, like internet connections or larger data files
• Creation of a graphical interface using the host's display or web server

Communication

Communication is easy. Arduino and Python have simple methods for establishing serial communication.

Arduino

void setup() {
Serial.begin(9600); //Initialize serial communication at 9600 baud
}
void loop() {
Serial.println('hello');
}


Python

from serial import *
ser = Serial( "/dev/ttyACM0" , 9600 )

while 1:


Incomplete Messages

One of the most difficult issues with this sort of serial communication is ensuring that commands are received in entirety. If you send "1000" from Python, and want Arduino to read it as shown below, Arduino might read "10" and then in another loop() right afterward read "00".

char incoming[11] = "          ";
int i = 0;
while (Serial.available() > 0) {
i++;
}
//Convert the incoming string into an integer!
int newNumber = atoi(incoming);


Fixed Length Packets

One way to solve this in an efficient manner is to use a fixed length for commands and wait until there are enough bytes waiting in the buffer. The downside is that no commands may be issued with a length longer than the fixed length, and requires remaining length be wasted.

Python

ser.write('%10d' % 1000 ) #pad the number so it is 10 characters long


Now just add a condition so that no reading is done unless a full command is waiting in the serial buffer.

Arduino

if ( Serial.available() >= 10 ) {
char incoming[11] = "          ";
int i = 0;
while (Serial.available() > 0) {
i++;
}
//Convert the incoming string into an integer!
newNumber = atoi(incoming);
}


Delineation

Another way to solve this problem is to delineate commands by placing a special character at the end of each command to signify that the command is complete. The problem with this way is that the length of the incoming string is unknown, and a long or improperly formed command could overflow a fixed length array. To overcome this limitation, a dynamic class is usually used. The String object is a good solution as it can be easily converted back into a character array. Maintaining data types with C++ strings can quickly become confusing, and it is extremely important that the delineation character is never used in the command. There are some special command characters in ASCII that would be good choices.

Multiple Command Types

You can send different commands over the same communication line by attaching a prefix to the command. For example, speed and position could be sent as "p000001000" and "s000000200" to tell the Arduino to go to position 1000 at a speed of 200.

Python

ser.write('p%9d' % 1000 ) #send position, padded to 9 (plus 1 command char)
ser.write('s%9d' % 200 )  #send speed, padded to 9 (plus 1 command char)


Arduino

int position, speed;
if ( Serial.available() >= 10 ) {
//read the first character as the command

char incoming[10] = "         ";
int i = 0;
i++;
}
//Convert the incoming string into an integer, based on command
if ( command == 'p' ) {
position = atoi(incoming);
}
else if ( command == 's' ) {
speed = atoi(incoming);
}
else {
//The command was not one of the recognized characters
Serial.println("COMMAND ERROR - Not recognized");
}
}


Now that your communication is established, it is up to you to figure out what to do with the data on either end.

Splitting a String

Introduction

There are times when a string is recieved, but rather than the entire string, just a piece of the string is desired. Unfortunately, there does not appear to be a simple way to handle strings in C++. Therefore, I have devised a way to split a string based on comma separation.

This way of splitting strings is rather crude and refinement for it will be worked on, but for immediate use, the current function is given with two examples of how it can be altered and used.

Coding

Splitting Strings - Two Characters

This code was used in a project that controlled a robot via computer. The computer sent data through an XBee to an Arduino that served as the brains. That Arduino would get the string from the computer, pick it apart and find the important information. That information was then relayed to an Arduino that controlled the robot's motors. The single character that was sent to the motor Arduino then told which direction to move the robot in.

//Brain Code

char string[25];
char id[2];
char direct[2];

int ii=0;

void setup() {
Serial.begin(9600);           // set up Serial library at 9600 bps
Serial1.begin(9600);
//Serial.println("Motor test!");
}

void loop() {
}

void serialEvent() {
int i=0;
if (Serial.available()) {
delay(50);
while(Serial.available()) {
}
string[i++]='\0';
splitString(string);
if (id[0] == 'M') {
Serial1.print(direct[0]);
}
}
}

void splitString(char* chars) {
char val1[15]={};
char val2[15]={};

int i=0;
int cnt_id,cnt_val1,cnt_val2;

//get identifier
while(chars[i] != ',' && i<25) {
i++;
if (chars[i] == ',' || chars[i]=='\0') {
for(int j=0;j<i;j++) {
id[j] = chars[j];
cnt_id=j;
}
id[cnt_id+1]='\0';
//Serial.println(id);
}
}

i++; //skips the comma

while(chars[i] != '\0' && i<25) {
i++;
if (chars[i] == ',' || chars[i]=='\0') {
for(int j=cnt_id+2;j<i;j++) {
direct[j-(cnt_id+2)] = chars[j];
cnt_val1=j-2;
}
direct[cnt_val1+1]='\0';
//Serial.println(direct);
}
}
}

A question may arise of why even bother with this code? Why not directly send to the motors which direction to move? And in this case, yes, that would have been much simpler. However, this is one part of a much bigger project where more than just motor information will be sent, so the first character being sent in will indicate which part of the robot it pertains to.

Splitting Strings - Getting Floats

Often times, it may be necessary to send actual number values, whether that is a float or an integer, through serial. Therefore, there needs to be a way to recover that data. It can be sent as a byte, but floats and larger integers may not fit into a byte.

For example, in a project it was necessary to send a string like "L,1234.5678,2345.6789" through serial to an Arduino. This is intepretted as sending a Location to the Arduino with the following coordinates. This would involve both splitting up the string and turning the number values into floats.

Unfortunately, there are not very elegant ways to handle strings in C, so two functions had to be made by scratch to split the string. In this particular example, this was the only type of string that was going to be sent to the Arduino, so code was made to split this specific string, but it can be adapted to other means.

The following code shows how the string is split:

void splitString(char* chars, char* id, double &numX, double &numY) {
char val1[15]={};
char val2[15]={};

int i=0;
int cnt_id,cnt_val1,cnt_val2;
//get identifier
while(chars[i] != ',' && i<25) {
i++;
if (chars[i] == ',' || chars[i]=='\0') {
for(int j=0;j<i;j++) {
id[j] = chars[j];
cnt_id=j;
}
id[cnt_id+1]='\0';
}
}
i++; //skips the comma

//get first float
while(chars[i] != ',' && i<25) {
i++;
if (chars[i] == ',' || chars[i]=='\0') {
for(int j=cnt_id+2;j<i;j++) {
val1[j-(cnt_id+2)] = chars[j];
cnt_val1=j-2;
}
val1[cnt_val1+1]='\0';
CharToFloat(val1, numX, cnt_val1+1);
}
}
i++; //skips the comma
//get second float
while(chars[i] != '\0' && i<25) {
i++;
if (chars[i] == ',' || chars[i]=='\0') {
Serial.println(chars[i]);
for(int j=cnt_id+cnt_val1+4;j<i;j++) {
val2[j-(cnt_id+cnt_val1+4)] = chars[j];
cnt_val2=j;
}
val2[cnt_val2+1]='\0';
CharToFloat(val2, numY, cnt_val2+1);
}
}
}

It may be noticed that in this case, a function CharToFloat is called. This function is explained in another tutorial. It is one method for turning character arrays into more precise floats.

Character Array to Float

Introduction

Sometimes it is necessary to turn character arrays into floats. However, precision can be an issue when using some of the current functions. The following function turns character arrays into a float that is split from the front half and the back half. This is one method for a more precise float.

Coding

The following code shows the CharToFloat function that turns the split Character Array into a float. It should be noted that the function splits the float into a forward half and a back half. This is due to the Arduino's capabilities. Floats can only ever have 7 digits, which means if you need anymore than that, the accuracy of the float decreases. It will remember 7 of the numbers and then make the best guess it can for the rest. This can be a problem if precision is key.

And, no, using double will not fix the problem. In the Arduino, float and double are the same thing. Therefore, splitting the float into two sections can retain the accuracy with some inconvenience.

void CharToFloat(char* chars, double* value, int count) {
int i=0, l=0;
float multiplier;
float front =0.0, behind =0.0;
value = 0.0;

//before demical point
while(chars[i]!='.' && i<count) {
i++;
if (chars[i]=='.') {
int q=i;
for(int j=i; j>0; j--) {
multiplier=1;
for(int k=q; k>1; k--) {
multiplier *= 10;
}
front+=(chars[l]-'0')*multiplier;
l++;
q--;
}
l++;
}
}

int n=i;
//after demical point
while(chars[n]!='\0' && i<count) {
n++;
if (chars[n]=='\0') {
int q=n, l=n-1;
for(int j=n-1; j>i; j--) {
multiplier=1;
for(int k=q-(i+2); k>=0; k--) {
multiplier = 0.1*multiplier;
}

behind+=(chars[l]-'0')*multiplier;
l--;
q--;
}
}
}
value[0]=front;
value[1]=behind;
}

This may not be the most elegant way to turn a character array into a float, but it works. Needless to say, this does not appear to be common practice, but seems like it might be a common problem.

Arduino to Arduino Serial Communication

Introduction

It is possible to chain Arduinos together in such a way as to get communication between the two. Having Arduino-Arduino communication can be useful for many projects, such as having one Arduino to run motors and having another sense the surroundings and then relay commands to the other Arduino. This can be done in several methods, using I2C and Serial, to list a few.

This tutorial will focus on Arduino-Arduino communication through the serial ports (RX and TX).

Schematic

The schematic below shows how to connect the two Arduinos together. This shows two Unos, but if a Mega is used, it can be connected to any of the Serial ports on the Mega as long as that is accounted for in the code.

There has to be a common ground between the two or else it will not function properly. Also, note that TX goes to RX and RX goes to TX.

Coding

When sending things through serial, everything is sent in bytes. These bytes are then read one byte at a time by the other Arduino. When it is just characters being sent through the serial, it is relatively easy to convert from characters to bytes. However, if there are both characters and numbers are going through, this can lead to messing up the data because a number and a character can have the same byte value, but that does not make them the same. Numbers are also tricky because they may not actually fit in the byte.

Simple Code

The easiest way to get around this is to try to avoid using characters and numbers at the same time. This can be done by sending one character across, each with a different meaning. A good example of this comes from the Arduino Physical Pixel tutorial.

Upload the Physical Pixel code, which can be found in the Arduino IDE under: File >> Examples >> Communication, onto one Arduino.

void setup() {  Serial.begin(9600);}void loop() {  Serial.print('H');  delay(1000);  Serial.print('L');  delay(1000);}

When this is run, the LED attached to Pin 13 on the Arduino with the Physical Pixel code should flash on and off at a frequency of 0.5 Hz. To make sure this is actually the code doing that, the delays can always be changed in the above code.

In this code the job of 'H' was to turn an LED on and the job of 'L' was to turn the LED off. This can easily be applicable to getting various characters triggering more reactions.

However, depending on the application, this may not be enough and more drastic code may be required.

Complex Code

For sending data from one Arduino to another in a form that cannot be simplified, there are other options. One option is to turn everything sent from the Sender Arduino into characters and then have the Receiver Arduino read in the characters. The data is actually sent as bytes, but the Arduino can convert from characters to bytes and vice versa.

Sender Code

The sender code changes characters into bytes and, if necessary, it changes number values into characters before turning it into bytes. Below is a sample of the Sender code:

//Sender Codechar str[4];void setup() {  Serial.begin(9600);}void loop() {  int value=1234; //this would be much more exciting if it was a sensor value    itoa(value, str, 10); //Turn value into a character array  Serial.write(str, 4);}

The receiver will then receive the byte array from the other Arduino and interpret it there. Below is the code for the receiver. Note that this code is intended for a Mega since it will interpret the data received from the other Arduino and then print to the Serial Monitor what it received so that the user can check it. This debugging can be avoided by using an Uno and then printing what was found onto an LCD screen that uses I2C communication.

//Receiver Codechar str[4];void setup() {  Serial.begin(9600);  Serial1.begin(9600);}void loop() {  int i=0;  if (Serial1.available()) {    delay(100); //allows all serial sent to be received together    while(Serial1.available() && i<4) {      str[i++] = Serial1.read();    }    str[i++]='\0';  }  if(i>0) {    Serial.println(str,4);  }}

There is one flaw with this program as it is now. It results in only a character array, so if the integers were desired, they are lost without further work on the data.

Further tutorials have been made to show how this data may be manipulated by splitting strings or getting floats from the character arrays.

First, to understand why things are done this way, it should be known that a bool (boolean true/false) is only 1 bit. 1 for true, 0 for false. However, computers have an addressing system for memory, which cannot go directly to a single bit. An address usually goes to a 8 bit chunk of memory (a byte), which is also usually the same size as an int data type.

Think of it like trying to write a postal address to a room in a house. The address will take you to the house, but not inside. So, we can't just keep it in its own variable.

Furthermore, it would be wasteful to waste 7 bits for every bool declared. 8 bools can be put all into one integer - all next to each other in memory - to save space. How do you seperate them? How do you get just one bit out of a chunk of bits? With boolean logic!

Port Manipulation

To be as efficient, Arduino groups pins together into 8 bit "int" variables. Using boolean logic, you can perform operations on pins yourself, instead of using the built-in functions. This is called Port Manipulation. There are 3 groups of 3 variables. First, the pins are broken up into groups of 8 based on number.

• D: Arduino digital pins 0 to 7
• B: Arduino digital pins 8 to 13
• C: Arduino analog pins 0 to 5

Then, there are 3 types of registers which can perform different actions, each with a the corresponding letter replacing the '#':

• DDR#: Data Direction Register.
• Sets whether the each pin is read from or written to.
• PORT#: Port I/O
• Can write to each pin a high or low state, but can also be read
• PIN#: Pin Input
• Can read the current pin states of the pins in input mode.

Pins are oranized in the register from lowest number at the right, to highest number at the left In this example, pins 11 through 13 are set as INPUT. Pins 11 and 13 are currently high at the moment, but pin 12 is low.

Pin:NANAPin 13Pin 12Pin 11Pin 10Pin 9Pin 8
Decimal Value1286432168421
PINB00101000
SelectP1300100000
SelectP1100001000

As you can see, if you were to print the value of PINC with pins 13 and 11 high but 12 low, the value with 32 + 8 = 40.

To select a single pin out of the PINC register, bitwise AND it with an int in the same place as the pin. So, PINB & SelectP13 = 13, or 0B00100000. Conditions in C++ will be true for any nonzero value. If Pin 13 were low, then the result would have been 0, or 0B00000000.

Programming Example

First, you have to set whether the pins are in read or write mode. Since this is often done exclusively in setup and only once per program, it is not as important to optimize this. It may be easiest to just use pinMode() to set the states instead of the more advanced ways described below with the DDR# register.

void setup() {
pinMode(11, INPUT);
pinMode(12, INPUT);
pinMode(13, INPUT);
}
void loop() {
//This condition is a single CPU operation    //pins 11,12, and 13 are all in the PINB group at the left    if ( PINB & 0B11100000 ) {
Serial.println("Pin 11, 12, or 13 were high");
}

//this condition requires dozens of operations
Serial.println("Pin 11, 12, or 13 were high");
}

}


In the above example, the slower second method each digitalRead must first figure out which register the pin is in, select it with a bitwise and, and return it to the condition. Then, each pin state must be ORd together.

Obviously, this case is not a typical one, but there are other uses. For example, one could write to several pins at once. This optimal method becomes extremely important when speed is an issue. When reading pins every few microseconds on interrupts, it can be beneficial to first store the whole register into a buffer, then do the required comparisons later in order to insure that all changes are being captured. Otherwise, data could be lost if the interrupt function is interrupted before it can complete.

Build Arduino Sketches from CLI with Make

Reasons

The Arduino IDE has a lot of nice features. It's so easy, it's really one of the main reasons why you would choose to buy an Arduino over other options. It can be annoying sometimes though. If you want to distance yourself from the IDE, but still like the Arduino plaform, it's really as easy as just making a really simple text file and running "make".

By getting a command line interface, you can also automate the build and upload process. You can detect ports, or upload to multiple Arduinos at once.

Installation

Ubuntu command:

sudo apt-get install avrdude make gcc-avr arduino-mk

Usage

Create a text file called "Makefile" in the same folder as your project

ARDUINO_DIR  = /usr/share/arduino

TARGET = projectName         # The same as your ino file name
BOARD_TAG    = uno           # can also be mega2560
ARDUINO_PORT = /dev/ttyACM0  # be sure to change this to the port used by your board
#Can add Arduino libraries. Example:#ARDUINO_LIBS = EEPROM

ARDUINO_DIR  = /usr/share/arduino
AVR_TOOLS_PATH = /usr/bin

include /usr/share/arduino/Arduino.mk


Once you have that file, all you need to do is just say:

make upload

If you aren't using an Arduino Uno, you can check which boards are available with:

make show_boards

It might be helpful to just autodetect all of the Arduinos connected and upload the same image to all of them. Here is a nice simple way to do that with bash:

Makefile:

ARDUINO_DIR  = /usr/share/arduino

TARGET = tempTargetName
BOARD_TAG    = uno
ARDUINO_PORT = ${arduino} ARDUINO_DIR = /usr/share/arduino AVR_TOOLS_PATH = /usr/bin include /usr/share/arduino/Arduino.mk Then make a bash file. This will be executed instead of the make command. make.sh: #!/bin/bash #look for any Arduinos. #The current ones were connected recently and within the same minute for a in ls -lt /dev/ttyACM* | awk 'BEGIN{first = 1} {if (first) {current =$9; first = 0} if ( $9 == current ) { print$10} else{exit} }' 
do
echo "uploading to $a" make arduino=$a upload

Wiring

The serial controller (or backpack) takes 5V, so connect the 5V and GND to the 5V and GND on the Arduino. The SDA and SCL pins are trickier. Depending on your Arduino, it could go any number of places, as seen in the table at the right.

 Board SDA SCL Uno A4 A5 Mega2560 20 21 Leonardo 2 3 Due 20 21

The most common board is the Uno, and the wiring of it can be seen here. Where SDA is the blue wire and SCL is the green wire - as is convention.

Coding

This code displays the information shown in the pictures above. It requires that you have some libraries installed. I have attached the version I used for convenience and preservation. However, the library is originally available from here, and a more up-to-date version may be available there.

The library must be installed in your Arduino folder. The folder location is:

 Windows %HOMEPATH%/My Documents/Arduino/ibraries/ OS X ~/Documents/Arduino/libraries/ Linux ~/Documents/Arduino/libraries/

Download the LiquidCrystal library .zip folder and extract the whole folder into the libraries folder for your system above.

#include <Wire.h>
#include <LiquidCrystal_I2C.h>

// Address can be changed by soldering A0, A1, or A2
// Default is 0x27

// map the pin configuration of LCD backpack for the LiquidCristal class
#define BACKLIGHT_PIN 3
#define En_pin  2
#define Rw_pin  1
#define Rs_pin  0
#define D4_pin  4
#define D5_pin  5
#define D6_pin  6
#define D7_pin  7

void setup() {
lcd.begin(20,4);        // 20 columns by 4 rows on display

lcd.setBacklight(HIGH); // Turn on backlight, LOW for off

lcd.setCursor ( 0, 0 );            // go to the top left corner
lcd.print("robotic-controls.com"); // write this string on the top row
lcd.setCursor ( 0, 1 );            // go to the 2nd row
lcd.print("  HD44780 / LCD2004 "); // pad string with spaces for centering
lcd.setCursor ( 0, 2 );            // go to the third row
lcd.print("  20x4 i2c display  "); // pad with spaces for centering
lcd.setCursor ( 0, 3 );            // go to the fourth row
lcd.print("Test increment: ");
}

int n = 1; // a global variable to track number of display refreshes

void loop() {
lcd.setCursor (16,3);         // go to col 16 of the last row
lcd.print(n++,DEC);           // update the display with a new number
// - overwrites previous characters
// - be sure new number is more digits
delay(500);                   // wait half a second before another update
}
Attachments:

Raspberry Pi

The Raspberry Pi is like a cross between a microcontroller like the Arduino and a full Linux desktop computer. It is much more computationally capable than an Arduino, and has the advantage of being able to use PC grade hardware like monitors, speakers, and nearly any USB device. However, it does not have as many GPIO pins available and operates at 3.3V instead of 5V like many Arduinos. The reason is that the Raspberry Pi is actually designed to be an inexpensive computer, not a microcontroller. It is inexpensive at just $25 or$35, and is extremely popular. As a result, there is a lot of support and documentation around for it, unlike other micocromputers.

One of the great advantages of a microcomputer, aside from the improved hardware and peripheral support, is that you get to use high level programming languages like python and even OpenGL for 3D displays. Image processing is easily done using simple webcams and using OpenCV, which the Arduino is far too underpowered to do. Since the Raspberry Pi is so popular, there are some great libraries that make it very easy to interface with the GPIO - even ones that imitate the familiar Arduino interface.

Raspberry Pi Introduction

Setup

The Raspberry Pi minimally needs a micro USB-B cord to power it. If you have a phone charger, aside from an iPhone, it will likely use this cable since the EU made it mandatory for smartphones. So, you probably don't even need to buy another wall adapter or cable if you look around. You can also plug it into a computer to power it, though you are not able to communicate with the computer over it. Additionally, an Ethernet cable connecting it to the same LAN as a computer is one of the easiest ways to get started. Unless you can figure out what IP address the Raspberry Pi will get, you will also need a keyboard and a monitor or tv capable of using either HDMI or the yellow RCA connector.

The Raspberry Pi does not come with an SD card, which you will also need. You will need to install an operating system on it as well, so it should be at least 4GB to be comfortable. Some SD cards are faster than others. Higher speed is denoted by a higher "class" number. This class will primarily effect install, startup, and upgrade times and there is no mandatory minimum.

SD Installation

Once you have it all set up, you will need to install the operating system to the SD card. I do not know of any reason not to use Raspbian unless you are both very experienced in Linux and already familiar with the Raspberry Pi (why would you be reading this?). Head over to the download page and get an up to date image of Raspbian. Then extract the .img from the .zip using whatever you usually use to unzip a file.

• Linux & Mac: sudo dd if=path_of_your_image.img of=/dev/XXXX bs=1M
• Windows: Use Win32DiskImager

Be extra sure to "eject" the disk after the imager is done regardless of the OS you use. You might be able to get away with it most of the time, but there will definitely be some changes waiting in the buffer even if you use dd.

Booting

Simply plug in the Raspberry Pi with the SD card and everything plugged into it. There is no power button. The default login username is "pi" and the password is "raspberry"

Raspbian GNU/Linux 7 raspberrypy tty1raspberrypi login: pipassword:

It is completely normal for the password field to not show any of your typing. It is a security feature.

GUI

If you want to start into a graphical environment, all you need to do is type "startx" and then hit enter.

pi@raspberrypi ~ $startx Updating and Installing Installing and upgrading things on your Raspberry Pi is really easy, but a little different than usual. The easiest way requires a little learning. If you don't want to learn the easy way, you'll still have to follow along a little bit. First, open a terminal. You can get one either by not running startx after a boot, or by clicking LXTerminal on your desktop. This terminal is one of the reasons why Linux is so great for developers. Just about anything can be done from here easily once you know what to type. pi@raspberrypi ~$ sudo apt-get updatepi@raspberrypi ~ $sudo apt-get install synaptic The two commands above can be broken into parts. "sudo" says "do this as super user", which gives you administrative abilities for that command. "apt-get" is a program that manages software on the computer and can install or upgrade them from the internet. the "update" argument tells "apt-get" to check the server for new software, but not to actually upgrade or install anything. The second command tells "apt-get" to "install" the software called "synaptic". The Synaptic Package Manager is essentially a graphical way to do the same thing as apt-get. It is probably not installed by default because it requires so many other programs be installed in order to work. apt-get automatically finds and installs these programs for you before installing synaptic. If you don't want to learn this terminal based way of installing and updating things, you can just use Synaptic. "startx" if you haven't already, and click the icon in the bottom left and hover over "other" and scroll down to find "Synaptic Package Manager". From there, things should be pretty self explainatory. Now, to upgrade all the software on your system at once, all you need to do is: pi@raspberrypi ~$ sudo apt-get upgrade

Just one command and everything installed on there can be upgraded to the newest version.

If you don't know exactly what you're looking for when you want to install something, you can find it relatively easily from the command line. The first thing you should check is not by opening a web browser and trying downloading the software. You will, first, probably not find anything compatible with your Raspberry Pi, and it will not be automatically updated if it were. Instead, try:

pi@raspberrypi ~ $apt-cache search wormsatanks - tank-battling game bsdgames - collection of classic textual unix games hedgewars - Worms style game labrea - a "sticky" honeypot and IDS libspf2-2 - library for validating mail senders with SPF libspf2-dev - Header and development libraries for libspf2 p3scan - transparent POP3-proxy with virus- and spam-scanning spfquery - query SPF (Sender Policy Framework) to validate mail senders warmux - turn-based artillery game on 2D maps warmux-dbg - debugging symbols for the WarMUX game warmux-servers - stand alone server and game index server for WarMUXpi@raspberrypi ~$ sudo apt-get install hedgewars


"apt-cache search" searches the descriptions of the easily available software. In this example, I wanted a game similar to Worms, and found hedgewars. Once you find what you are looking for, you use "apt-get install" to install the software.

Remote Access

Once you have things set up, you can access a command prompt to the Raspberry Pi from another computer by installing:

pi@raspberrypi ~ $sudo apt-get install openssh-server avahi-daemon This installs the openssh server, which is probably already installed, and the avahi-daemon, which lets you connect using the Raspberry Pi's name rather than the IP address. From the other computer, use either PuTTY or ssh if you are on Windows or Mac/Linux respectively. Windows does not resolve .local addresses by default. I believe this is solved if you even have so much as iTunes installed, but if not, you may have to install Bonjour. If you don't want to do that, you can follow the IP address method shown below. Once in putty, simply enter raspberrypi.local in the hostname field, or the IP if the .local name is not working. It will warn you about the fingerprints because you have not connected to this device before. Hit yes and PuTTY will remember this fingerprint for next time and warn you if it changes. Then login as "pi" and use the password "raspberry". From Linux or a Mac, run the command: ssh pi@raspberrypi.local If you can't connect, try using the Raspberry Pi's IP address, which can be found by running the ifconfig command: pi@raspberrypi ~$ ifconfig
UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
RX packets:12776 errors:0 dropped:0 overruns:0 frame:0
TX packets:3604 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:12519918 (11.9 MiB)  TX bytes:625071 (610.4 KiB)

Raspberry Pi Pinout and IO

There are some great libraries that make it really easy to use the pins on the Raspberry Pi. It has relatively few pins and are a little less powerful than what you might expect from a microcontroller. Aside from those limitations, you should also keep in mind that pin manipulation is not done in a real time environment. Unlike an Arduino, which only runs your program, the Raspberry Pi takes turns running many programs like a normal desktop. While your program might be able to recieve the majority of the processor's attention, it will not be able to use all of it. Likewise, timing events may be slightly less reliable too. As great as Python is, it is even less reliable because of a process called garbage collection. It is not a problem for most situations, but it is definitely something to keep in mind.

There are two kinds of numbers to specify which pin you want to use. There is the physical pin number, which altenate sideways increasing from top to bottom. For nearly any device, if you look carefully on the board, there is an indicator near the "1" pin on a header. This is even true of integrated circuit (IC) chips. Unlike with ICs, orienting the pins with that indicator in the top left, the pin numbers are increased from left to right and top to bottom. The reason this appears differently on P5 is because the indicator is on the bottom side.

The BCM GPIO number is the number that the processor uses to differentiate the pins. Obviously, pins like 5V and GND cannot be addressed since they only have their one purpose and cannot be changed. As a result, the BCM number is different than the header number. It is important to keep track of which addressing system you are using. It might help you to remember that BCM is a reference to the signal name on the Broadcom datasheet for the processor on the Raspberry Pi.

You should also know that the pinout information only pertains to the revision 2 version of the board. You can tell that you are not using a revision 1 board by the presense fo the P5 holes. P5 was added in revision 2. Revision 1 is essentially the same, but has quite a few pins missing.

BCM
GPIO#
GPIO#
3.3V 2 1 5V
29 GPIO9 4 3 GPIO8 28
31 GPIO11 6 5 GPIO10 20
GND 8 7 GND
BCM
GPIO#
GPIO#
3.3V 1 2 5V
2 SDA* 3 4 5V
3 SCL* 5 6 GND
4 GPIO7 7 8 TX 14
GND 9 10 RX 15
17 GPIO0 11 12 PWM0 18
27 GPIO2 13 14 GND
22 GPIO3 15 16 GPIO4 23
3.3V 17 18 GPIO5 24
10 SPI MOSI 19 20 GND
9 SPI MISO 21 22 GPIO6 25
11 SPI SCLK 23 24 SPI CE0 8
GND 25 26 SPI CE1 7

*The i2c pins conveniently have 1.8 kΩ pullup resistors.

Each of these pins have their own limitations:

Limits
Pin TypeMax Current
3.3V 50mA
5V 200mA
GPIO 16mA @ 3.3V
Total GPIO 51mA
Input High >1.3V
Input Low <0.8V

It might be possible that the "total GPIO" and "3.3V" limitations both refer to the same number. Needless to say, in any case you really cannot put much on the GPIO or 3.3V power. Really, it's just two LEDs and you're already at 40-60mA.

Given the voltage and current limits of these pins, you will likely find yourself needing ways around them. A logic level converter is good for interfacing 3.3V serial and GPIO to 5V devices. Shift registers and I/O port expanders are both good for both being able to deliver more current and adding more pins. There are all sorts of ways around these limitations, but simple stuff like MOSFETS, transistors, and voltage regulators can be the most effective. There are also no analog inputs, so to read voltage you can use an Analog to Digital Converter (ADC). One way to get around all of these limitations is to use an ATmega or Arduino for any controls, and just use the Raspberry Pi for anything resource intensive, but interfacing the two still requires a logic level converter since they usually operate at different voltages. There are 3.3V Arduino variants though.

Using the GPIO Pins

GPIO is easily done with the rpi-gpio python package. First, make sure you have it installed by opening a terminal (like LXterminal)

sudo apt-get updatesudo apt-get install python-dev python-rpi.gpio

Then, just make a plain text file using whatever editor you like containing something like this:

import RPi.GPIO as ioimport time
io.setmode(io.BCM)# io.BCM says use the BCM GPIO numbering system for pins. # io.BOARD will use the actual "header" numbers.# reading from a GPIO pininputPinNumber = 18                     # the BCM GPIO pin number, 12 if io.BOARDio.setup(inputPinNumber, io.IN)         # similar to pinMode in Arduinoif io.input(inputPinNumber):            # read the pin, use in if condition    print("Pin 18 is high")else:    print("Pin 18 is low")# writting to a GPIO pinoutputPinNumber = 23                    # the BCM GPIO pin number, 16 if io.BOARDio.setup(outputPinNumber, io.OUT)while True:                             # loop forever    io.output(outputPinNumber, io.HIGH) # set the pin output to high (3.3V)    time.sleep(0.5)                     # wait a half a second    io.output(outputPinNumber, io.LOW)  # set the pin output to low (0V)    time.sleep(0.5)                     # wait another half a second before looping

You will need to run it as root, since GPIO manipulation requires root priviliges.

pi@raspberrypi ~ $sudo python pinIOtest.py Using i2C and SPI These serial connections require a little more setup because they require kernel modules, which are like drivers. They disabled them by default because "many users don't need them". I guess we are one of the few, huh? You can copy these lines to a terminal like LXterminal or in SSH. The stuff after the # is just comments to explain what they do. You don't need to retype it, but it won't hurt if you're copy and pasting either. sudo rm /etc/modprobe.d/raspi-blacklist.conf # remove their "disable"sudo modprobe i2c-bcm2708 i2c-dev # enable modules now without restartecho i2c-bcm2708 | sudo tee /etc/modules # add the i2c driver to startupecho i2c-dev | sudo tee /etc/modules # add other i2c driver to startupsudo apt-get install python-smbus i2c-tools # install some useful i2c tools Now you can see what's connected to i2c with this neat command: pi@raspberrypi ~$ sudo i2cdetect -y 1
0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: 20 -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --

The output shows that there is a device connected to the i2c bus and has an address of 20.  This is the default address for an MCP230 port expander, which is what I have hooked up to it. If nothing were hooked up to the SCL and SDA that was i2c compatible, there would be "--" there, just like everything else.

Now, to use i2c in a Python program, use the SMBus package:

import smbusbus = smbus.SMBus(1)address = 0x20write_byte(addr,val)read_byte(addr)

Syncing Files on the Raspberry Pi

Introduction

Syncing files automatically from a Raspberry Pi is a good idea to make sure that nothing gets lost the Pi breaks. The problem is that due to the unusual ARM architecture, most of the common methods for syncing are not available. Dropbox does not have an ARM package. Google Drive never had a Linux client. There are ways around these limitations either by use of lower quality third party applications to interface with the major sync solutions or by use of open source and self hosted solutions.

Sparkleshare

Sparkleshare is a self-hosted solution. Sparkleshare uses Git on its backend, so it's particularly good for text files. You can also use a git host like Bitbucket. It provides an easy to use graphical interface and is very easy to set up

On the Raspberry Pi:

pi@raspberrypi:~# sudo apt-get install sparkleshare

Building Sparkleshare (unnecessary if using the package from apt-get):

#install all mono stuff, which is probably (definitely) overkill
pi@raspberrypi:~# sudo apt-get install libmono-2.0-dev mono-complete gtk-sharp2 libwebkit-cil-dev libnotify0.4-cil libnotify-cil-dev
pi@raspberrypi:~# mkdir apps ; cd apps
pi@raspberrypi:~# tar -xzf sparkleshare-linux-1.1.0-tar.gz
pi@raspberrypi:~# cd sparkleshare-1.1.0/
pi@raspberrypi:~# ./configure
pi@raspberrypi:~# make
pi@raspberrypi:~# sudo make install

On your "host" computer (unnecessary if using third party Git host)

root@evan-ubuntu:~# sudo su && cd
# Fetch the Dazzle script
root@evan-ubuntu:~# curl https://raw.github.com/hbons/Dazzle/master/dazzle.sh \
--output /usr/bin/dazzle && chmod +x /usr/bin/dazzle
# Run the initial setup
root@evan-ubuntu:~# dazzle setup
# Link SparkleShare clients using their Client ID found in the status menu

Client ID:  ssh-rsa AAAAB3NzaC1yc2EAAAADAQ... ... ...TnTL4SK1+7gYKT raspberrypi

# Create a new project. Add as many as you need
root@evan-ubuntu:~# dazzle create raspberry # raspbery project or directory nameProject "raspberry" was successfully created.
To link up a SparkleShare client, enter the following
details into the "Add Hosted Project..." dialog:

Remote Path: /home/storage/raspberry


Setup on the client side uses a GUI:

pi@raspberrypi:~# DISPLAY=:0 sparkleshare start

Grive

Grive is the unnofficial Google Drive client for Linux. Google has no official linux client, but in this specific case that is actually a good thing, in a weird way, because the open source version can be built from source and can run on the Raspberry Pi's ARM processor.

First, try installing from the repos. In a lot of debian archives, grive is now available. At the point of writting this though, it is not currenlty in the Raspbian repo, but is in other Debian repos.

pi@raspberrypi ~ $sudo apt-get install grive  Building Grive from Source If that package does not work, you can build it from source, but it takes a really long time to build. This will add quite a few packages to your Raspbian - a couple hundred MB worth, which takes more than a couple minutes to install. The build also takes about 20 minutes. sudo apt-get install cmake git build-essential libgcrypt11-dev libjson0-dev libcurl4-openssl-dev libexpat1-dev libboost-filesystem-dev libboost-program-options-dev binutils-dev libqt4-core libqt4-dev libboost-test-dev libboost-filesystem-dev libboost-program-options-dev libboost-system-dev libyajl-devpi@raspberrypi$ mkdir ~/apps ; cd ~/apps
pi@raspberrypi ~/apps $git clone git://github.com/Grive/grive.gitpi@raspberrypi ~/apps$ cd grivepi@raspberrypi ~/apps/grive $cmake . -- Found libgcrypt: -L/lib/arm-linux-gnueabihf -lgcrypt -- Found JSON-C: /usr/lib/arm-linux-gnueabihf/libjson.so -- Boost version: 1.49.0 -- Found the following Boost libraries: -- program_options -- filesystem -- unit_test_framework -- system -- Found libbfd: /usr/lib/libbfd.so -- Found libiberty: /usr/lib/libiberty.a -- Boost version: 1.49.0 -- Found the following Boost libraries: -- program_options -- Boost version: 1.49.0 -- Configuring done -- Generating done -- Build files have been written to: /home/pi/apps/grive If you do not add these scope resolution operators, the compiler does not seem to know to use the Boost library. It might also have to do with the sizes of variables on the ARM processor versus normal. pi@raspberrypi ~/apps/grive$ nano libgrive/src/drive/State.cc
void State::Write( const fs::path& filename ) const
{
Json last_sync ;

last_sync.Add( "sec", Json((boost::uint64_t) m_last_sync.Sec() ) );
last_sync.Add( "nsec", Json((boost::uint64_t) m_last_sync.NanoSec() ) );

Json result ;

result.Add( "change_stamp", Json((boost::uint64_t) m_cstamp) ) ;

std::ofstream fs( filename.string().c_str() ) ;
fs << result ;
}

Now that you've patched it a little bit, you can actually build it. This takes a while.

pi@raspberrypi ~/apps/grive $make [ 1%] Building CXX object libgrive/CMakeFiles/grive.dir/src/json/JsonParser.cc.o /tmp/ccN9aaS9.s: Assembler messages: /tmp/ccN9aaS9.s:1258: Warning: swp{b} use is deprecated for this architecture [ 3%] Building CXX object libgrive/CMakeFiles/grive.dir/src/json/ValBuilder.cc.o /tmp/cc0qtdOv.s: Assembler messages: /tmp/cc0qtdOv.s:1317: Warning: swp{b} use is deprecated for this architecture [ 5%] Building CXX object libgrive/CMakeFiles/grive.dir/src/json/JsonWriter.cc.o [ 7%] Building CXX object libgrive/CMakeFiles/grive.dir/src/json/ValResponse.cc.o [ 8%] Building CXX object libgrive/CMakeFiles/grive.dir/src/util/File.cc.o /tmp/ccCrhkFO.s: Assembler messages: /tmp/ccCrhkFO.s:1317: Warning: swp{b} use is deprecated for this architecture [ 10%] Building CXX object libgrive/CMakeFiles/grive.dir/src/util/Config.cc.o [ 12%] Building CXX object libgrive/CMakeFiles/grive.dir/src/util/StdStream.cc.o [ 14%] Building CXX object libgrive/CMakeFiles/grive.dir/src/util/Exception.cc.o /tmp/cca93GMZ.s: Assembler messages: /tmp/cca93GMZ.s:1298: Warning: swp{b} use is deprecated for this architecture [ 16%] Building CXX object libgrive/CMakeFiles/grive.dir/src/util/OS.cc.o /tmp/cchdH7ge.s: Assembler messages: /tmp/cchdH7ge.s:1258: Warning: swp{b} use is deprecated for this architecture [ 17%] Building CXX object libgrive/CMakeFiles/grive.dir/src/util/DateTime.cc.o /tmp/ccnsT4HV.s: Assembler messages: /tmp/ccnsT4HV.s:1258: Warning: swp{b} use is deprecated for this architecture [ 19%] Building CXX object libgrive/CMakeFiles/grive.dir/src/util/StringStream.cc.o [ 21%] Building CXX object libgrive/CMakeFiles/grive.dir/src/util/SignalHandler.cc.o [ 23%] Building CXX object libgrive/CMakeFiles/grive.dir/src/util/Crypt.cc.o /tmp/ccx344KH.s: Assembler messages: /tmp/ccx344KH.s:1258: Warning: swp{b} use is deprecated for this architecture [ 25%] Building CXX object libgrive/CMakeFiles/grive.dir/src/util/MemMap.cc.o [ 26%] Building CXX object libgrive/CMakeFiles/grive.dir/src/util/log/CompositeLog.cc.o [ 28%] Building CXX object libgrive/CMakeFiles/grive.dir/src/util/log/DefaultLog.cc.o [ 30%] Building CXX object libgrive/CMakeFiles/grive.dir/src/util/log/CommonLog.cc.o [ 32%] Building CXX object libgrive/CMakeFiles/grive.dir/src/util/log/Log.cc.o [ 33%] Building CXX object libgrive/CMakeFiles/grive.dir/src/xml/String.cc.o [ 35%] Building CXX object libgrive/CMakeFiles/grive.dir/src/xml/NodeSet.cc.o /tmp/ccshU8Rr.s: Assembler messages: /tmp/ccshU8Rr.s:1284: Warning: swp{b} use is deprecated for this architecture [ 37%] Building CXX object libgrive/CMakeFiles/grive.dir/src/xml/Node.cc.o /tmp/cc03tDy6.s: Assembler messages: /tmp/cc03tDy6.s:1284: Warning: swp{b} use is deprecated for this architecture [ 39%] Building CXX object libgrive/CMakeFiles/grive.dir/src/xml/TreeBuilder.cc.o /tmp/ccEaKl2M.s: Assembler messages: /tmp/ccEaKl2M.s:1258: Warning: swp{b} use is deprecated for this architecture [ 41%] Building CXX object libgrive/CMakeFiles/grive.dir/src/bfd/Debug.cc.o [ 42%] Building CXX object libgrive/CMakeFiles/grive.dir/src/bfd/SymbolInfo.cc.o [ 44%] Building CXX object libgrive/CMakeFiles/grive.dir/src/bfd/Backtrace.cc.o Linking CXX static library libgrive.a [ 82%] Built target grive Scanning dependencies of target btest [ 83%] Building CXX object libgrive/CMakeFiles/btest.dir/test/btest/UnitTest.cc.o [ 85%] Building CXX object libgrive/CMakeFiles/btest.dir/test/btest/ValTest.cc.o /tmp/ccK8TOeR.s: Assembler messages: /tmp/ccK8TOeR.s:1331: Warning: swp{b} use is deprecated for this architecture [ 87%] Building CXX object libgrive/CMakeFiles/btest.dir/test/btest/JsonValTest.cc.o /tmp/ccOAUEHb.s: Assembler messages: /tmp/ccOAUEHb.s:1331: Warning: swp{b} use is deprecated for this architecture Linking CXX executable btest [ 87%] Built target btest Scanning dependencies of target grive_executable Linking CXX executable grive [ 89%] Built target grive_executable [ 91%] Generating src/moc_MainWnd.cxx [ 92%] Generating ui_MainWindow.h Scanning dependencies of target bgrive_executable [ 94%] Building CXX object bgrive/CMakeFiles/bgrive_executable.dir/src/DriveModel.cc.o /tmp/ccgDURnf.s: Assembler messages: /tmp/ccgDURnf.s:1731: Warning: swp{b} use is deprecated for this architecture [ 96%] Building CXX object bgrive/CMakeFiles/bgrive_executable.dir/src/MainWnd.cc.o [ 98%] Building CXX object bgrive/CMakeFiles/bgrive_executable.dir/src/main.cc.o [100%] Building CXX object bgrive/CMakeFiles/bgrive_executable.dir/src/moc_MainWnd.cxx.o Linking CXX executable bgrive [100%] Built target bgrive_executable Well, now that that's over, the install process seems to need an extra doc, so we'll just add an empty one, which might not be necessary. pi@raspberrypi ~/apps/grive$ mkdir /home/pi/apps/grive/bgrive/doc/
pi@raspberrypi ~/apps/grive $touch /home/pi/apps/grive/bgrive/doc/grive.1pi@raspberrypi ~/apps/grive$ sudo make install

Usage

First, set up a folder to sync your stuff to. Then you open a long authentication link in a browser and log in to your Google account. It will then give you a long code to copy back to the program. It is important that your current directory is the directory you wish to sync with your Google Drive before you do this.

pi@raspberrypi ~ $mkdir ~/gdrive/ ; cd ~/gdrivepi@raspberrypi ~/gdrive$ grive -a
-----------------------
Please go to this URL and get an authentication code:

-----------------------
Please input the authentication code here: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Synchronizing folders
Synchronizing files... ... ... ...

Now, to set up automatic sync, it unfortunately has to be done this somewhat simplistic way:

pi@raspberrypi ~ $mkdir ~/bin/pi@raspberrypi ~$ echo "#! /bin/bash
> cd ~/gdrive/
> grive" > ~/bin/gsyncpi@raspberrypi ~ $chmod +x ~/bin/gysncpi@raspberrypi ~$ crontab -e*/10 * * * * /home/pi/bin/gsync

Now, your Google Drive will sync to your to your Raspberry Pi every 10 minutes. There might be a way to do this every time a file changes on the Raspberry Pi using inotifywait, but it would not sync changes from Google Drive until there is a change locally.

dropfuse

Dropfuse is not one of the best or most secure options, but Dropbox is a really nice service. Dropfuse is a third party script that relies on the "share link" feature. It does not actually connect to your entire Dropbox account. It will only connect to a single shared folder. Log onto dropbox.com, navigate to the folder you want sync'd and click "share link". You'll find a link like this:

https://www.dropbox.com/sh/AAAAAAAAAAAAAAA/BBBBBBBBBB

Modify the link yourself to this format:

https://www.dropbox.com/s/AAAAAAAAAAAAAAA

The install process is relatively easy.

pi@raspberrypi ~ $sudo apt-get install python-pyquerypi@raspberrypi ~$ sudo usermod -a -G fuse pipi@raspberrypi ~ $mkdir appspi@raspberrypi ~$ mkdir Dropboxpi@raspberrypi ~ $cd appspi@raspberrypi ~/apps$ git clone git://github.com/arekzb/dropfuse.git
Cloning into 'dropfuse'...
remote: Counting objects: 38, done.
remote: Compressing objects: 100% (21/21), done.
remote: Total 38 (delta 19), reused 34 (delta 17)
Receiving objects: 100% (38/38), 14.16 KiB, done.
Resolving deltas: 100% (19/19), done.pi@raspberrypi ~/apps $cd dropfuse sudo python dropfuse.py https://www.dropbox.com/s/c6ecc2plwconh5x ~/Dropbox & To stop the service, do this: pi@raspberrypi ~$ fusermount -u Dropbox

BitTorrent Sync

A word of warning, btsync causes lots of networking issues. On an Ubuntu machine, it can cause 10% of your dns queries to timeout. The symptoms are less severe on a Windows computer, but still problematic for seemingly anything but web browsing, which seems unaffected. I cannot recommend BitTorrent Sync as a result, but maybe they will have patched it by the time you are reading this, so here goes.

In concept, this might be the best of any of the options. It is distributed and peer to peer. It deals with binary files well. You can share over the internet without DNS or public IPs. It is extremely simple to set up, despite what all is going on under the hood.

wget http://btsync.s3-website-us-east-1.amazonaws.com/btsync_arm.tar.gz
tar xzf btsync_arm.tar.gz
sudo ln -s /lib/arm-linux-gnueabihf/ld-linux.so.3 /lib/ld-linux.so.3
./btsync

Then just take a browser and visit http://raspberrypi.local:8888/.

BeagleBone

Introduction

The BeagleBone is like a combination between a microcontroller (like Arduino) and a small Linux desktop. It is most similar to a Raspberry Pi, but with more pinouts and a faster processor. The BeagleBone has several variants, the most recent edition being the BeagleBone Black (aka BBB), which retails for $45 USD. It is a great choice if you are going to add image or video processing to your robot. An Arduino is nowhere near powerful enough to handle images. Arduino, however, is extremely easy to use and extremely well documented with a massive community. Against a Raspberry Pi, it's a harder choice to make. It's more expensive, but has a processor that's faster and capable of running ARMv7 operating systems like Ubuntu and Android, where a Raspberry Pi is substantially more limited. A Raspberry Pi is easier to use and has a much larger community behind it, but the BeagleBone has some powerful hardware features. If you are undecided, the good news is that they are both really cheap, both run Python, and have very similar ways of accessing GPIO (the /sys/ directory), so really you could change your mind midway through a project and not face too much of a setback. BeagleBone Black with Angstrom Introduction Angstrom Linux is what ships on the BeagleBones. It's kind of terrible because I think everyone when they first get it will say, oh I should run opkg upgrade so that everything is up to date. Guess what? That breaks the boot. It won't startup anymore. I don't know how to fix it or what goes wrong. You'll get three LED's on, no USB connection on either the mass media or network, and it'll never come online on the LAN because it won't start up. If you want things to be up to date, you may want to install Ubuntu. On the other hand, it is pretty lightweight and is pre-configured in a lot of ways that other distros don't have by default. For example, the cloud9 editor is kind of nice. Installing Images Whether you have a BeagleBone or BeagleBone Black, you can use the Angstrom-Cloud9-IDE-GNOME-eglibc-ipk*.img.xz They both run ARM7 and the image has the NEON optimization. The image for the BeagleBone Black might have additional features, but it's the same Angstrom with less features as far as I can tell. sudo suxz -cd ./Angstrom-Cloud9-IDE-GNOME-****.img.xz > /dev/sdd URLs Check out the tutorial page on http://beaglebone.local/. There are some neat node.js buttons on http://beaglebone.local/bonescript.html The very cool Cloud9 IDE is available on http://beaglebone.local:3000/ If you're on windows and don't have an SSH client that you like, there's GateOne SSH client availble in-browser at https://beaglebone.local/ If those URLs don't work, then you might try replacing beaglebone.local with 192.168.7.2. If that doesn't work, there might be something wrong with your installation. You could re-flash another image. Tweaks Disable GNOME autostart If you want a graphical environment to develop and test on, that's fine, but a lot of the time your deployment will be headless. Well, you can have your cake and eat it too. update-rc.d -f gdm removesystemctl disable gdmmv /lib/systemd/system/gdm.service ~/gdm.backup.servicesystemctl --system daemon-reload There are probably more steps there than are necessary, but I couldn't get it to stay down for a while, so try them all. Then if you want to start your graphical environment at any point, just login and run gdm Install locate Locate is an awesome tool for searching the filesystem really quickly. opkg install findutilsupdatedb Run a Script on Startup (cron) nano ~/startup.sh #put something in /tmp/ so we can see if this rantouch /tmp/WINNING#turn off the heartbeatecho 0 > /sys/class/leds/beaglebone\:green\:usr0/brightness chmod +x ~/startup.shenv EDITOR=nano crontab -e@reboot /bin/bash /home/root/startup.sh Run a Script on Startup (systemd) Angstrom uses systemd, so it has a few things different than a Debian/Ubuntu system. Not sure why you'd want to do it this way. It's a lot harder than cron. First make a script you want to run on startup. You might just use this bash file to launch all your other processes. If you do, throw a & at the end of each line to run them in background. nano ~/mystartup.sh #!/bin/bash touch /tmp/WINNING chmod +x ~/mystartup.sh After making an executable script, make a service for systemd to use. nano /lib/systemd/system/mystartup.service [Unit] Description=My own script to run on startupConditionPathExists=|/usr/bin After=local-fs.target [Service] Type=oneshot ExecStart=/home/root/mystartup.sh systemctl --system daemon-reloadsystemctl enable mystartup.service To load it and test it, try: systemctl start mystartup.servicels -l /tmp/WINNINGjournalctl Note that journalctl is apparently the new way of doing a "less /var/log/syslog" Benchmarks Compare the benchmarks to those of the Raspberry Pi (wiki) using this package (zip). Also compare to my Ubuntu BBB tests. Processor Info root@beaglebone:~# cat /proc/cpuinfo processor : 0 model name : ARMv7 Processor rev 2 (v7l) BogoMIPS : 990.68 Features : swp half thumb fastmult vfp edsp thumbee neon vfpv3 tls CPU implementer : 0x41 CPU architecture: 7 CPU variant : 0x3 CPU part : 0xc08 CPU revision : 2 Hardware : Generic AM33XX (Flattened Device Tree) Revision : 0000 Serial : 0000000000000000  Dhrystone At 3059570 dhrystones per second, the BBB with Angstrom is almost 4 times faster than a Raspberry Pi (809061) with Raspbian on it. However, it is about 10% slower than it could be with Ubuntu on it (3319960). ########################################## Dhrystone Benchmark, Version 2.1 (Language: C or C++) Optimisation Opt 3 32 Bit Register option not selected 10000 runs 0.01 seconds 100000 runs 0.11 seconds 200000 runs 0.18 seconds 400000 runs 0.13 seconds 800000 runs 0.26 seconds 1600000 runs 0.52 seconds 3200000 runs 1.05 seconds 6400000 runs 2.09 seconds Final values (* implementation-dependent): Int_Glob: O.K. 5 Bool_Glob: O.K. 1 Ch_1_Glob: O.K. A Ch_2_Glob: O.K. B Arr_1_Glob[8]: O.K. 7 Arr_2_Glob8/7: O.K. 6400010 Ptr_Glob-> Ptr_Comp: * 94584 Discr: O.K. 0 Enum_Comp: O.K. 2 Int_Comp: O.K. 17 Str_Comp: O.K. DHRYSTONE PROGRAM, SOME STRING Next_Ptr_Glob-> Ptr_Comp: * 94584 same as above Discr: O.K. 0 Enum_Comp: O.K. 1 Int_Comp: O.K. 18 Str_Comp: O.K. DHRYSTONE PROGRAM, SOME STRING Int_1_Loc: O.K. 5 Int_2_Loc: O.K. 13 Int_3_Loc: O.K. 7 Enum_Loc: O.K. 1 Str_1_Loc: O.K. DHRYSTONE PROGRAM, 1'ST STRING Str_2_Loc: O.K. DHRYSTONE PROGRAM, 2'ND STRING From File /proc/cpuinfo processor : 0 model name : ARMv7 Processor rev 2 (v7l) BogoMIPS : 297.40 Features : swp half thumb fastmult vfp edsp thumbee neon vfpv3 tls CPU implementer : 0x41 CPU architecture: 7 CPU variant : 0x3 CPU part : 0xc08 CPU revision : 2 Hardware : Generic AM33XX (Flattened Device Tree) Revision : 0000 Serial : 0000000000000000 From File /proc/version Linux version 3.8.13 (koen@rrMBP) (gcc version 4.7.3 20130205 (prerelease) (Linaro GCC 4.7-2013.02-01) ) #1 SMP Mon May 20 17:07:58 CEST 2013 Nanoseconds one Dhrystone run: 326.84 Dhrystones per Second: 3059570 VAX MIPS rating = 1741.36  OpenSSL Again, the BBB on Angstrom proves to be significantly faster than the Raspberry Pi. About 4 times faster or way more. However, the comparison to the BBB with Ubuntu are actually the opposite. Angstrom is faster by about 10%. The difference? No NEON FPU optimizations on Ubuntu! root@beaglebone:~# openssl speed;OpenSSL 1.0.0j 10 May 2012 built on: Wed Apr 3 21:06:55 CEST 2013 options:bn(64,32) rc4(ptr,int) des(idx,risc1,2,long) aes(partial) idea(int) blowfish(idx) compiler: arm-angstrom-linux-gnueabi-gcc -march=armv7-a -mthumb-interwork -mfloat-abi=softfp -mfpu=neon -mtune=cortex-a8 --sysroot=/build/v2012.12/build/tmp-angstrom_v2012_12-eglibc/sysroots/olinuxino-a13 -fPIC -DOPENSSL_PIC -DOPENSSL_THREADS -D_REENTRANT -DDSO_DLFCN -DHAVE_DLFCN_H -DL_ENDIAN -DTERMIO -O2 -pipe -g -feliminate-unused-debug-types -Wall -DHAVE_CRYPTODEV -DUSE_CRYPTODEV_DIGESTS The 'numbers' are in 1000s of bytes per second processed. type 16 bytes 64 bytes 256 bytes 1024 bytes 8192 bytes md2 0.00 0.00 0.00 0.00 0.00 mdc2 2200.18k 2903.10k 3079.22k 3123.71k 3131.59k md4 5415.82k 20091.55k 62372.30k 131555.57k 194939.46k md5 4617.55k 16804.97k 50871.15k 102349.66k 145803.90k hmac(md5) 7419.73k 25105.91k 67753.84k 117279.85k 149212.21k sha1 4689.06k 15086.80k 37111.10k 58582.77k 70082.56k rmd160 4321.96k 13657.71k 33189.03k 51514.42k 61322.19k rc4 51274.46k 57055.08k 58599.86k 59068.36k 59196.82k des cbc 15641.44k 16844.09k 17096.95k 17186.71k 17143.13k des ede3 5966.27k 6118.46k 6149.65k 6173.80k 6179.74k idea cbc 15220.99k 16040.11k 16331.43k 16378.86k 16340.16k seed cbc 21797.27k 23300.32k 23793.27k 23880.09k 23956.81k rc2 cbc 13306.59k 14101.91k 14234.37k 14302.09k 14325.00k rc5-32/12 cbc 0.00 0.00 0.00 0.00 0.00 blowfish cbc 27004.49k 29706.03k 30572.82k 30746.37k 30866.58k cast cbc 26993.30k 29720.81k 30501.50k 30798.77k 30854.70k aes-128 cbc 27466.35k 29851.57k 30765.55k 31029.95k 31033.71k aes-192 cbc 23934.83k 25819.16k 26408.67k 26625.71k 26651.49k aes-256 cbc 21310.20k 22657.92k 23204.56k 23356.48k 23362.27k camellia-128 cbc 28544.43k 31191.34k 31965.01k 32352.21k 32362.51k camellia-192 cbc 23092.30k 24841.16k 25474.06k 25586.30k 25650.86k camellia-256 cbc 23167.57k 24852.70k 25346.39k 25612.71k 25614.38k sha256 4648.14k 11368.65k 21020.95k 26654.38k 29045.86k sha512 969.92k 3858.49k 5574.64k 7650.79k 8548.17k whirlpool 1872.39k 3901.80k 6372.60k 7553.37k 7996.82k aes-128 ige 25801.92k 28261.82k 29148.35k 29319.28k 28924.91k aes-192 ige 22733.70k 24548.07k 25245.12k 25323.28k 25036.29k aes-256 ige 20328.61k 21757.95k 22204.79k 22366.69k 22090.91k sign verify sign/s verify/s rsa 512 bits 0.002286s 0.000191s 437.4 5244.1 rsa 1024 bits 0.011637s 0.000559s 85.9 1790.5 rsa 2048 bits 0.068425s 0.001828s 14.6 546.9 rsa 4096 bits 0.444783s 0.006260s 2.2 159.7 sign verify sign/s verify/s dsa 512 bits 0.001946s 0.002152s 513.9 464.7 dsa 1024 bits 0.005539s 0.006413s 180.5 155.9 dsa 2048 bits 0.018094s 0.021652s 55.3 46.2 sign verify sign/s verify/s 160 bit ecdsa (secp160r1) 0.0011s 0.0048s 935.6 210.4 192 bit ecdsa (nistp192) 0.0011s 0.0052s 873.1 192.9 224 bit ecdsa (nistp224) 0.0015s 0.0069s 679.8 144.8 256 bit ecdsa (nistp256) 0.0020s 0.0099s 509.9 100.8 384 bit ecdsa (nistp384) 0.0041s 0.0218s 245.0 45.8 521 bit ecdsa (nistp521) 0.0093s 0.0490s 107.4 20.4 163 bit ecdsa (nistk163) 0.0040s 0.0081s 247.2 124.2 233 bit ecdsa (nistk233) 0.0078s 0.0154s 128.3 65.1 283 bit ecdsa (nistk283) 0.0119s 0.0276s 84.3 36.2 409 bit ecdsa (nistk409) 0.0283s 0.0632s 35.3 15.8 571 bit ecdsa (nistk571) 0.0634s 0.1443s 15.8 6.9 163 bit ecdsa (nistb163) 0.0040s 0.0087s 252.3 115.5 233 bit ecdsa (nistb233) 0.0076s 0.0166s 130.8 60.3 283 bit ecdsa (nistb283) 0.0118s 0.0302s 84.6 33.2 409 bit ecdsa (nistb409) 0.0284s 0.0718s 35.2 13.9 571 bit ecdsa (nistb571) 0.0637s 0.1660s 15.7 6.0 op op/s 160 bit ecdh (secp160r1) 0.0041s 246.8 192 bit ecdh (nistp192) 0.0044s 229.8 224 bit ecdh (nistp224) 0.0057s 174.7 256 bit ecdh (nistp256) 0.0083s 121.1 384 bit ecdh (nistp384) 0.0177s 56.6 521 bit ecdh (nistp521) 0.0406s 24.6 163 bit ecdh (nistk163) 0.0039s 255.5 233 bit ecdh (nistk233) 0.0075s 132.8 283 bit ecdh (nistk283) 0.0136s 73.6 409 bit ecdh (nistk409) 0.0312s 32.1 571 bit ecdh (nistk571) 0.0718s 13.9 163 bit ecdh (nistb163) 0.0042s 236.7 233 bit ecdh (nistb233) 0.0082s 121.3 283 bit ecdh (nistb283) 0.0152s 65.7 409 bit ecdh (nistb409) 0.0357s 28.0 571 bit ecdh (nistb571) 0.0825s 12.1  BeagleBone Black with Ubuntu Introduction The BeagleBone Black is a very powerful and affordable microcontroller - superior to an Arduino Uno in a lot of ways. It's fast enough to be used as a desktop computer, yet it has more pinouts than an Uno. With the BeagleBone Black priced at$45, it's really a great value compared to an Arduino ($35) or even a Raspberry Pi ($35).

An Arduino, while power-efficient and reliable, is incapable of high performance use cases like image processing. Even the ARM based Arduino Due is thousands of times slower than the BeagleBone Black. It can't even parse a JPEG (the library won't fit in the flash). A BeagleBone or Raspberry Pi, however, can easily process live streams from USB webcams and OpenCV.

The BeagleBone Black is significantly faster and more capable than the comperable $35 Raspberry Pi Model B. Both have the same RAM, HDMI out, and Ethernet, but the BeagleBone Black has superior IO (more and faster) and has a faster processor capable of running Ubuntu, where the Raspberry Pi cannot due to its older architecture. Remember, Raspberry Pi was intended to be an educational tool to teach kids to program, not to help you hack together a robot. The BBB has two extra processors dedicated to effectively manage the pinouts. The downside? The pre-installed OS (Angstrom) at this point in time will break if you do a package upgrade. Not only will it never boot again once it finishes updating, but it also uses too much of the /tmp/ filesystem and stalls halfway though. You can run Ubuntu on it, but there isn't much of a point, since it's basically incapable of having a desktop UI or using OpenGL as far as I can tell. There's no reason why it shouldn't be possible. In fact, LXDE and XFCE sort of work. This leads to the bigger problem. The documentation, support, and community behind BeagleBone is nowhere near that of the Raspberry Pi, let alone Arduino (which has the best by far). Setup A lof of this information is based on the BeagleBone Ubuntu wiki. Installing to an SD Card From a Linux computer that has the target microSD card in, download a recent .tar.xz from this wiki or our upload of the 13.04 image, in case theirs disappears. Then run these bash commands: tar xJf ubuntu-13.04-console-armhf-2013-05-18.tar.xzcd ubuntu-13.04-console-armhf-2013-05-18sudo ./setup_sdcard.sh --mmc /dev/sdd --uboot bone_dtb --svideo-ntsc --swap_file 1024 Be sure to change /dev/sdd to whatever the SD card is on your computer. If you are using a european TV/monitor, you should set it to PAL instead of NTSC. It seems to default to PAL though. If you get flickering, also consider finding a more powerful power supply for the BeagleBone. Supposedly, it needs 500mA of 5V, but it seems to like to have more than that available. The copy process can take a while - especially the rootfs file sync phase. Be patient. Boot Plug in the microSD card with the contacts facing down. It sticks out about an eigth of an inch when all the way in. It doesn't quite seem to be in all the way, but it is. Push down the user boot button. Keep it down while plugging it in. The boot button is the button right next to the microSD card slot. After pressing the button while powering on the first time, it will not be necessary again. Eventually, you'll see the penguin at the right and you can stop holding the button down. If you pay attention to the LEDs, you can see when the OS is loaded too. SSH Access You can either get a keyboard, micro HDMI to HDMI cable, HDMI TV or monitor, and a mini usb power cable, or you can just plug it into a desktop with the mini USB cable. To access the Ubuntu loaded BeagleBone Black by SSH over USB, use this command: ssh ubuntu@192.168.7.2 The password will be temppwd. To change the password, just run "passwd" once you log in. Internet In order to access the internet do download the extra packages, you'll need to plug in an ethernet cable. Theoretically, you should be able to forward the desktop's connection with a bridge, but it is probably more trouble than it's worth. Network Manager on ubuntu has an easy way to share connections though. "Edit connections..." then edit the BeagleBone's USB connection (probably Wired Connection 2). In the IPv4 tab, change the "method" to "shared". I assume something similar can be done on Windows. Swapfile Add a swapfile, if it wasn't by your install process. sudo mkdir -p /var/cache/swap/ sudo dd if=/dev/zero of=/var/cache/swap/swapfile bs=1M count=1024 sudo chmod 0600 /var/cache/swap/swapfile sudo mkswap /var/cache/swap/swapfile sudo swapon /var/cache/swap/swapfilesudo nano /etc/fstab/var/cache/swap/swapfile none swap sw 0 0 Install Packages? There are a few packages provided in the /boot/ directory. They might already be installed, but I think they are not installed by default due to licensing or something. cd /boot/uboot/tools/pkgs sudo bash ti-omapconf.shsudo bash imx-sdma-firmware.shsudo bash ti-omapdrm.shsudo bash ti-tidspbridge.shsudo bash ti-uim.shsudo bash ti-wlink-firmware.sh XFCE Graphics (Don't Bother) It's easy to install the graphical environment. It might be impossible to get it to work though. The installation will use up an additional 1 GB of space on top of the default install size of 0.5 GB, so it may not be a great idea to do on a 2GB card. sudo apt-get updatesudo apt-get install xubuntu-desktopsudo shutdown -r now This install takes about an hour, and includes really a full desktop linux desktop. This is probably more than you want. Mine seems to crash after a few seconds of being booted into a graphical environment. It doesn't matter what environment I choose either. I've tried XFCE, LXDE, and Unity under LightDM and LXDM. XFCE comes the closest to staying on the longest. Unity does not work due to a lack of OpenGL. There do not seem to be any drivers for it available yet. I don't think Unity will work at all, since compiz can't find OpenGL extensions, but the lightdm login will come up, as you can see. Before you get too down on not having a familiar environment, don't worry about it! Just get a good way of syncing between the BeagleBone Black and your desktop. That way you can keep your faster and familiar computing environment and keep your BeagleBone slim and specialized for what you're actually using it for. Sync I chose BitTorrent Sync due to the simplicity to set up. It isn't open source, but neither is Dropbox and a lot of us still use it. It is one of the few sync options that offers very easy to install ARM-compatible builds. There is a trick to setting it up though, you have to add a symlink first. wget http://btsync.s3-website-us-east-1.amazonaws.com/btsync_arm.tar.gztar xzf btsync_arm.tar.gzrm btsync_arm.tar.gz LICENSE.TXTsudo ln -s /lib/arm-linux-gnueabihf/ld-linux.so.3 /lib/ld-linux.so.3./btsync Then just take a browser and visit http://192.168.7.2:8888/ if it is connected by USB, or http//arm.local:8888/ if on LAN. If you are more concerned about privacy and open source software, maybe check out building your own with rsync, or look at lipsync, which uses rsync and some filesystem monitoring. Bash Autocomplete Autocomplete when tab is pressed (practically necessary!). It is for some reason necessary to install it and then reinstall it, which is definitely odd, but whatever. sudo apt-get install bash-completionsudo apt-get install --reinstall bash-completion Locale Set your locale, so it stops bugging you about it being set to C by default. sudo nano /etc/default/localeLANG=en_US.utf8sudo locale-gen en_US.utf8 Local Bin Folder Add a home bin directory mkdir ~/binnano ~/.bashrc#append to the bottom to automatically add home bin to the pathPATH=$PATH:/$HOME/bin/ Dim the Lights Put some masking tape or painter's tape over those 4 LED's because they are really annoyingly bright. That might sound like a joke, but if you have it blinking in the corner of your eye non-stop for hours it will actually start to give you a headache. They never stop blinking either. One of them is the Linux Kernel Heartbeat light. They're brighter than normal LEDs too. Why? Dunno. They're blue? Blue LEDs are usually dimmer though. It's hard to even take a picture of the board while it's on! I really can't believe how rediculously annoying they are... Alternatively, instead of putting tape over it, you could run this to actually turn them off. That's probably the right way to do this. Really, it's just the heartbeat that's annoying, but you can turn off the rest too if you want. # just turn off the heartbeatecho 0 > /sys/class/leds/beaglebone\:green\:usr0/brightness# get rid of the rest tooecho 0 > /sys/class/leds/beaglebone\:green\:usr1/brightnessecho 0 > /sys/class/leds/beaglebone\:green\:usr2/brightnessecho 0 > /sys/class/leds/beaglebone\:green\:usr3/brightness If you're worried you won't be able to tell if it crashes, just look at the LAN leds or any of the other 3 indicators. They're always blinking too. Run a script at startup So here is a really neat trick: nano /home/ubuntu/bin/startup.sh #! /bin/bashecho 0 > /sys/class/leds/beaglebone\:green\:usr0/brightness chmod +x /home/ubuntu/bin/startup.shsudo susudo crontab -e @reboot /bin/bash /home/ubuntu/bin/startup.sh Isn't cron cool? Set Up Python GPIO is done essentially by just writting and writing to the special /sys/ folder. Check out this github project for a more familiar interface for it. Allow python to interface with i2c. sudo apt-get install python-smbus Benchmarks Compare the benchmarks to those of the Raspberry Pi (wiki) using this package (zip). Also compare to my Angstrom BBB tests. Dhrystone Running whetstone on the Beaglebone Black with Ubuntu compiled with just -O3 yields 3,319,960 dhrystones per second. A Raspberry Pi nets 809,061.5. The BeagleBone was able to do 4.1 times more operations per second. This is also 10% faster than the same BeagleBone Black with Angstrom, the default Linux distrobution, which ran at 3,059,570. The same test ran on a desktop computer with an AMD Phenom II x4 965 gets around 25,062,657. That's more 10% of a pretty powerful desktop, which I think is somewhat impressive. gcc dhry_1.c dhry_2.c dhry.h cpuidc.c -lm -O3 -o dhry./dhry##########################################Dhrystone Benchmark, Version 2.1 (Language: C or C++)Optimisation Opt 3 32 BitRegister option not selected 10000 runs 0.01 seconds 100000 runs 0.10 seconds 200000 runs 0.20 seconds 400000 runs 0.21 seconds 800000 runs 0.24 seconds 1600000 runs 0.48 seconds 3200000 runs 0.96 seconds 6400000 runs 1.93 seconds 12800000 runs 3.86 seconds Final values (* implementation-dependent):Int_Glob: O.K. 5 Bool_Glob: O.K. 1Ch_1_Glob: O.K. A Ch_2_Glob: O.K. BArr_1_Glob[8]: O.K. 7 Arr_2_Glob8/7: O.K. 12800010Ptr_Glob-> Ptr_Comp: * 94584 Discr: O.K. 0 Enum_Comp: O.K. 2 Int_Comp: O.K. 17 Str_Comp: O.K. DHRYSTONE PROGRAM, SOME STRINGNext_Ptr_Glob-> Ptr_Comp: * 94584 same as above Discr: O.K. 0 Enum_Comp: O.K. 1 Int_Comp: O.K. 18 Str_Comp: O.K. DHRYSTONE PROGRAM, SOME STRINGInt_1_Loc: O.K. 5 Int_2_Loc: O.K. 13Int_3_Loc: O.K. 7 Enum_Loc: O.K. 1 Str_1_Loc: O.K. DHRYSTONE PROGRAM, 1'ST STRINGStr_2_Loc: O.K. DHRYSTONE PROGRAM, 2'ND STRINGFrom File /proc/cpuinfoprocessor : 0model name : ARMv7 Processor rev 2 (v7l)BogoMIPS : 198.72Features : swp half thumb fastmult vfp edsp thumbee neon vfpv3 tls CPU implementer : 0x41CPU architecture: 7CPU variant : 0x3CPU part : 0xc08CPU revision : 2Hardware : Generic AM33XX (Flattened Device Tree)Revision : 0000Serial : 0000000000000000From File /proc/versionLinux version 3.8.13-bone18 (root@imx6q-sabrelite-1gb) (gcc version 4.7.3 (Ubuntu/Linaro 4.7.3-1ubuntu1) ) #1 SMP Thu May 16 21:04:48 UTC 2013Nanoseconds one Dhrystone run: 301.21Dhrystones per Second: 3319960VAX MIPS rating = 1889.56 OpenSSL This benchmark shows numbers that are 2-10x faster than those on the Raspberry Pi . However, Angstrom is faster by about 10%. The difference? Perhaps this package has no NEON FPU optimizations on Ubuntu. I also believe the BeagleBone has a special cryptography processor which might not be taken advantage of in this test. The Dhrystone test was compiled, this OpenSSL and is probably missing some optimization argument that the Angstrom package had. OpenSSL 1.0.1c 10 May 2012built on: Tue Mar 19 19:30:47 UTC 2013options:bn(64,32) rc4(ptr,char) des(idx,cisc,16,long) aes(partial) blowfish(ptr) compiler: cc -fPIC -DOPENSSL_PIC -DZLIB -DOPENSSL_THREADS -D_REENTRANT -DDSO_DLFCN -DHAVE_DLFCN_H -DL_ENDIAN -DTERMIO -g -O2 -fstack-protector --param=ssp-buffer-size=4 -Wformat -Werror=format-security -D_FORTIFY_SOURCE=2 -Wl,-Bsymbolic-functions -Wl,-z,relro -Wa,--noexecstack -Wall -DOPENSSL_NO_TLS1_2_CLIENT -DOPENSSL_MAX_TLS1_2_CIPHER_LENGTH=50 -DOPENSSL_BN_ASM_MONT -DOPENSSL_BN_ASM_GF2m -DSHA1_ASM -DSHA256_ASM -DSHA512_ASM -DAES_ASM -DGHASH_ASMThe 'numbers' are in 1000s of bytes per second processed.type 16 bytes 64 bytes 256 bytes 1024 bytes 8192 bytesmd2 0.00 0.00 0.00 0.00 0.00 mdc2 0.00 0.00 0.00 0.00 0.00 md4 7130.44k 28511.10k 79135.70k 142166.02k 185522.60kmd5 6735.29k 22954.62k 61948.74k 107186.00k 136339.07khmac(md5) 6964.12k 23296.17k 62451.29k 107847.13k 136203.64ksha1 6698.12k 20571.23k 46889.18k 69689.54k 81622.11krmd160 5756.90k 16751.42k 36409.79k 51751.17k 58911.17krc4 64964.35k 72925.41k 76732.39k 77427.41k 77922.96kdes cbc 17184.97k 18237.05k 18618.82k 18752.60k 18739.89kdes ede3 6574.42k 6735.54k 6804.62k 6794.36k 6817.50kidea cbc 0.00 0.00 0.00 0.00 0.00 seed cbc 21670.10k 22990.09k 23573.99k 23608.01k 23745.80krc2 cbc 12701.57k 13378.96k 13576.59k 13579.82k 13613.01krc5-32/12 cbc 0.00 0.00 0.00 0.00 0.00 blowfish cbc 27309.24k 29968.99k 30775.05k 31125.82k 31069.32kcast cbc 26848.41k 29213.50k 30071.18k 30396.65k 30340.54kaes-128 cbc 37250.31k 40851.65k 42063.71k 42548.23k 42491.55kaes-192 cbc 31962.79k 34354.75k 35324.32k 35672.31k 35698.43kaes-256 cbc 28581.52k 30449.05k 31271.64k 31611.70k 31551.61kcamellia-128 cbc 26676.56k 28496.71k 29167.33k 29344.13k 29277.50kcamellia-192 cbc 21532.49k 22621.60k 23114.57k 23195.84k 23143.08kcamellia-256 cbc 21538.22k 22695.82k 23031.27k 23209.75k 23145.82ksha256 9965.51k 24221.62k 43539.86k 54826.95k 58500.20ksha512 4207.69k 16757.43k 25271.78k 35145.54k 39798.78kwhirlpool 1579.78k 3265.95k 5289.78k 6313.06k 6654.97kaes-128 ige 34714.63k 38142.11k 39508.96k 39855.59k 39798.33kaes-192 ige 29820.66k 32531.41k 33528.70k 33661.52k 33790.63kaes-256 ige 27038.57k 29091.23k 29929.06k 30019.98k 30137.21kghash 49881.45k 60961.91k 65236.19k 66256.57k 66803.29k sign verify sign/s verify/srsa 512 bits 0.001070s 0.000107s 934.7 9379.4rsa 1024 bits 0.006119s 0.000332s 163.4 3009.0rsa 2048 bits 0.039563s 0.001208s 25.3 827.6rsa 4096 bits 0.285143s 0.004634s 3.5 215.8 sign verify sign/s verify/sdsa 512 bits 0.001092s 0.001191s 915.9 839.5dsa 1024 bits 0.003264s 0.003762s 306.3 265.8dsa 2048 bits 0.011669s 0.013505s 85.7 74.0 sign verify sign/s verify/s 160 bit ecdsa (secp160r1) 0.0006s 0.0024s 1577.7 416.5 192 bit ecdsa (nistp192) 0.0008s 0.0033s 1219.0 301.0 224 bit ecdsa (nistp224) 0.0010s 0.0045s 959.1 224.2 256 bit ecdsa (nistp256) 0.0013s 0.0058s 770.0 171.2 384 bit ecdsa (nistp384) 0.0030s 0.0155s 331.5 64.4 521 bit ecdsa (nistp521) 0.0064s 0.0351s 156.9 28.5 163 bit ecdsa (nistk163) 0.0020s 0.0067s 495.7 149.8 233 bit ecdsa (nistk233) 0.0042s 0.0122s 238.0 82.2 283 bit ecdsa (nistk283) 0.0064s 0.0219s 155.9 45.6 409 bit ecdsa (nistk409) 0.0171s 0.0488s 58.4 20.5 571 bit ecdsa (nistk571) 0.0409s 0.1130s 24.4 8.9 163 bit ecdsa (nistb163) 0.0020s 0.0072s 505.1 138.4 233 bit ecdsa (nistb233) 0.0042s 0.0134s 239.8 74.5 283 bit ecdsa (nistb283) 0.0064s 0.0247s 155.1 40.5 409 bit ecdsa (nistb409) 0.0172s 0.0549s 58.3 18.2 571 bit ecdsa (nistb571) 0.0410s 0.1288s 24.4 7.8 op op/s 160 bit ecdh (secp160r1) 0.0020s 501.6 192 bit ecdh (nistp192) 0.0028s 358.5 224 bit ecdh (nistp224) 0.0037s 272.1 256 bit ecdh (nistp256) 0.0050s 201.4 384 bit ecdh (nistp384) 0.0130s 77.2 521 bit ecdh (nistp521) 0.0295s 33.9 163 bit ecdh (nistk163) 0.0033s 301.6 233 bit ecdh (nistk233) 0.0060s 167.9 283 bit ecdh (nistk283) 0.0109s 91.5 409 bit ecdh (nistk409) 0.0241s 41.4 571 bit ecdh (nistk571) 0.0559s 17.9 163 bit ecdh (nistb163) 0.0036s 281.4 233 bit ecdh (nistb233) 0.0066s 152.2 283 bit ecdh (nistb283) 0.0122s 81.9 409 bit ecdh (nistb409) 0.0274s 36.5 571 bit ecdh (nistb571) 0.0638s 15.7 7z A Raspberry Pi would be expected to run 321 MIPS. Ubuntu BeagleBone gets 502 with the standard package, and 510 if you compile p7zip, showing that compiling is not really worth the effort unless it is a very important library that is proving to be a bottleneck for you. ubuntu@arm:~$ 7z b

7-Zip 9.20  Copyright (c) 1999-2010 Igor Pavlov  2010-11-18
p7zip Version 9.20 (locale=en_US.utf8,Utf16=on,HugeFiles=on,1 CPU)

RAM size:     495 MB,  # CPU hardware threads:   1
RAM usage:    419 MB,  # Benchmark threads:      1

Dict        Compressing          |        Decompressing
Speed Usage    R/U Rating  |    Speed Usage    R/U Rating
KB/s     %   MIPS   MIPS  |     KB/s     %   MIPS   MIPS

22:     345    99    341    336  |     7291    99    662    658
23:     329    98    341    336  |     7176    99    661    657
24:     315    98    344    339  |     7061    99    659    655
25:     304    98    354    347  |     6929    99    655    651
----------------------------------------------------------------
Avr:           98    345    339                99    659    655
Tot:           99    502    497

Switching Back to Angstrom

To revert to the default install, the image it shipped with is available here: http://beagleboard.org/latest-images. I like the one that comes with GNOME though.

# backupsudo dd if=/dev/sdX bs=8M | xz -c > myBeagleUbuntu.img.xz# re-imagexz -cd Angstrom-Cloud9-IDE-GNOME-eglibc-ipk-v2012.12-beaglebone-2013.04.13.img.xz > /dev/sdX
Attachments:

BeagleBone Black Built-In LEDs

There are four user LEDs on the BeagleBone. You can modify them, but they each have their own purposes by default. USER0 is the closest to the top in the picture at the right, and USER3 is the bottom one closest to the ethernet port.

• USER0 is the heartbeat indicator from the Linux kernel.
• USER1 turns on when the SD card is being accessed
• USER2 is an activity indicator. It turns on when the kernel is not in the idle loop.
• USER3 turns on when the onboard eMMC is being accessed.

You can change each of the LED's behaviors at the following locations:

/sys/class/leds/beaglebone\:green\:usr0//sys/class/leds/beaglebone\:green\:usr1//sys/class/leds/beaglebone\:green\:usr2//sys/class/leds/beaglebone\:green\:usr3/

Yeah, the LEDs are blue, but the folder is called green for some reason. Also, those colons make BASH freak out a bit, so pay attention to escape them.

If you explore those directories, things start to get interesting.

First, any write operatoins will require root privileges. The use of IO redirection will require that you be the root account, not just use sudo. This is only really applicable if you are not using Angstrom, where the root account is the default account.

root@beaglebone:~# cd /sys/class/leds/beaglebone\:green\:usr0/
root@beaglebone:/sys/class/leds/beaglebone:green:usr0# ls -l total 0
-rw-r--r-- 1 root root 4096 Jan  1 00:08 brightness
lrwxrwxrwx 1 root root    0 Jan  1 00:08 device -> ../../../gpio-leds.8
-r--r--r-- 1 root root 4096 Jan  1 00:08 max_brightness
drwxr-xr-x 2 root root    0 Jan  1 00:08 power
lrwxrwxrwx 1 root root    0 Jan  1 00:08 subsystem -> ../../../../../class/leds
-rw-r--r-- 1 root root 4096 Jan  1 00:08 trigger
-rw-r--r-- 1 root root 4096 Jan  1 00:00 ueventroot@beaglebone:/sys/class/leds/beaglebone:green:usr0# cat triggernone nand-disk mmc0 mmc1 timer oneshot [heartbeat] backlight gpio cpu0 default-on transient 

You can see that USER0 is in hearbeat trigger mode. I find that heartbeat to be annoying (it's so bright!). Let's get rid of it

Take Over a USER LED

You can change what LED blinks to indicate by changing the trigger. For example, GPIO would indicate GPIO activity.

In order to change these, you will need to become root by either using sudo bash or sudo su

Sudo alone will not help because of the I/O redirection used in these commands. You could do sudo nano trigger instead.

root@beaglebone:/sys/class/leds/beaglebone:green:usr0# echo none > triggerroot@beaglebone:/sys/class/leds/beaglebone:green:usr0# cat trigger[none] nand-disk mmc0 mmc1 timer oneshot heartbeat backlight gpio cpu0 default-on transient root@beaglebone:/sys/class/leds/beaglebone:green:usr0# echo 0 > brightness

Just a simple BASH loop:

while true; do echo 255 > brightness ; sleep 1; echo 0 > brightness; sleep 1; done;

OR you can use the timer built-in trigger

echo timer > triggerecho 500 > delay_offecho 50 > delay_on

You can even use it as a sort of PWM to dim the LED. There should be another way to do this, but this is all I've found.

echo timer > triggerecho 1 > delay_onecho 12 > delay_off

Interestingly, I think this should behave similar to the heartbeat. If the system crashes it would turn on or off completely.

BeagleBone Black Pins

Pinout Tables

These tables are based on the BeagleBone Black System Reference Manual (Creative Commons) by Gerald Coley of BeagleBoard.org. They aren't really available anywhere else on the internet, so I thought I'd transcribe them into a more available format.

The PROC column is the pin number on the processor.

The PIN column is the pin number on the expansion header.

The MODE columns are the mode setting for each pin. Setting each mode to align with the mode column will give that function on that pin. Each pin's mode can be set individually.

Note that the MODE5 column is absent. That is not a typo. It just doesn't do anything. The only exception is GPIO0_7 in expansion header P9 has a mmc0_sdwp

PINPROCNAMEMODE0MODE1MODE2MODE3MODE4MODE6MODE7
1,2 GND
3 R9 GPIO1_6 gpmc_ad6 mmc1_dat6         gpio1[6]
4 T9 GPIO1_7 gpmc_ad7 mmc1_dat7         gpio1[7]
5 R8 GPIO1_2 gpmc_ad2 mmc1_dat2         gpio1[2]
6 T8 GPIO1_3 gpmc_ad3 mmc1_dat3         gpio1[3]
7 R7 TIMER4 gpmc_advn_ale   timer4       gpio2[2]
8 T7 TIMER7 gpmc_oen_ren   timer7       gpio2[3]
9 T6 TIMER5 gpmc_be0n_cle   timer5       gpio2[5]
10 U6 TIMER6 gpmc_wen   timer6       gpio2[4]
11* R12 GPIO1_13 gpmc_ad13 lcd_data18 mmc1_dat5* mmc2_dat1 eQEP2B_in   gpio1[13]
12* T12 GPIO1_12 gpmc_ad12 lcd_data19 mmc1_dat4* mmc2_dat0 EQEP2A_IN   gpio1[12]
13* T10 EHRPWM2B gpmc_ad9 lcd_data22 mmc1_dat1* mmc2_dat5 ehrpwm2B   gpio0[23]
14* T11 GPIO0_26 gpmc_ad10 lcd_data21 mmc1_dat2* mmc2_dat6 ehrpwm2_tripzone   gpio0[26]
15* U13 GPIO1_15 gpmc_ad15 lcd_data16 mmc1_dat7* mmc2_dat3 eQEP2_strobe   gpio1[15]
16* V13 GPIO1_14 gpmc_ad14 lcd_data17 mmc1_dat6* mmc2_dat2 eQEP2_index   gpio1[14]
17* U12 GPIO0_27 gpmc_ad11 lcd_data20 mmc1_dat3* mmc2_dat7 ehrpwm0_synco   gpio0[27]
18 V12 GPIO2_1 gpmc_clk_mux0 lcd_memory_clk gpmc_wait1 mmc2_clk   mcasp0_fsr gpio2[1]
19* U10 EHRPWM2A gpmc_ad8 lcd_data23 mmc1_dat0* mmc2_dat4 ehrpwm2A   gpio0[22]
20* V9 GPIO1_31 gpmc_csn2 gpmc_be1n mmc1_cmd*       gpio1[31]
21* U9 GPIO1_30 gpmc_csn1 gpmc_clk mmc1_clk*       gpio1[30]
22 V8 GPIO1_5 gpmc_ad5 mmc1_dat5         gpio1[5]
23 U8 GPIO1_4 gpmc_ad4 mmc1_dat4         gpio1[4]
24 V7 GPIO1_1 gpmc_ad1 mmc1_dat1         gpio1[1]
25 U7 GPIO1_0 gpmc_ad0 mmc1_dat0         gpio1[0]
26 V6 GPIO1_29 gpmc_csn0           gpio1[29]
27* U5 GPIO2_22 lcd_vsync* gpmc_a8         gpio2[22]
28* V5 GPIO2_24 lcd_pclk* gpmc_a10         gpio2[24]
29* R5 GPIO2_23 lcd_hsync* gpmc_a9         gpio2[23]
30* R6 GPIO2_25 lcd_ac_bias_en* gpmc_a11         gpio2[25]
31* V4 UART5_CTSN lcd_data14* gpmc_a18 eQEP1_index mcasp0_axr1 uart5_rxd uart5_ctsn gpio0[10]
32* T5 UART5_RTSN lcd_data15* gpmc_a19 eQEP1_strobe mcasp0_ahclkx mcasp0_axr3 uart5_rtsn gpio0[11]
33* V3 UART4_RTSN lcd_data13* gpmc_a17 eQEP1B_in mcasp0_fsr mcasp0_axr3 uart4_rtsn gpio0[9]
34* U4 UART3_RTSN lcd_data11* gpmc_a15 ehrpwm1B mcasp0_ahclkr mcasp0_axr2 uart3_rtsn gpio2[17]
35* V2 UART4_CTSN lcd_data12* gpmc_a16 eQEP1A_in mcasp0_aclkr mcasp0_axr2 uart4_ctsn gpio0[8]
36* U3 UART3_CTSN lcd_data10* gpmc_a14 ehrpwm1A mcasp0_axr0   uart3_ctsn gpio2[16]
37* U1 UART5_TXD lcd_data8* gpmc_a12 ehrpwm1_tripzone mcasp0_aclkx uart5_txd uart2_ctsn gpio2[14]
38* U2 UART5_RXD lcd_data9* gpmc_a13 ehrpwm0_synco mcasp0_fsx uart5_rxd uart2_rtsn gpio2[15]
39* T3 GPIO2_12 lcd_data6* gpmc_a6   eQEP2_index     gpio2[12]
40* T4 GPIO2_13 lcd_data7* gpmc_a7   eQEP2_strobe pr1_edio_data_out7   gpio2[13]
41* T1 GPIO2_10 lcd_data4* gpmc_a4   eQEP2A_in     gpio2[10]
42* T2 GPIO2_11 lcd_data5* gpmc_a5   eQEP2B_in     gpio2[11]
43* R3 GPIO2_8 lcd_data2* gpmc_a2   ehrpwm2_tripzone     gpio2[8]
44* R4 GPIO2_9 lcd_data3* gpmc_a3   ehrpwm0_synco     gpio2[9]
45* R1 GPIO2_6 lcd_data0* gpmc_a0   ehrpwm2A     gpio2[6]
46* R2 GPIO2_7 lcd_data1* gpmc_a1   ehrpwm2B     gpio2[7]

* some pins are used by the internal storage (eMMC), and HDMI. 11-21 are used by eMMC.  27-46 are used by HDMI.

PINPROCNAMEMODE0MODE2MODE3MODE4MODE6MODE7
1,2 GND
3,4 DC_3.3V
5,6 VDD_5V
7,8 SYS_5V
9 PWR_BUT
10 A10 RESET_OUT
11 T17 gpmc_wait0 mii2_crs gpmc_csn4 rmii2_crs_dv mmc1_sdcd uart4_rxd_mux2 gpio0[30]
12 U18 gpmc_be1n mii2_col gpmc_csn6 mmc2_dat3 gpmc_dir mcasp0_aclkr_mux3 gpio1[28]
13 U17 gpmc_wpn mii2_rxerr gpmc_csn5 rmii2_rxerr mmc2_sdcd uart4_txd_mux2 gpio0[31]
14 U14 gpmc_a2 mii2_txd3 rgmii2_td3 mmc2_dat1 gpmc_a18 ehrpwm1A_mux1 gpio1[18]
15 R13 gpmc_a0 gmii2_txen rmii2_tctl mii2_txen gpmc_a16 ehrpwm1_tripzone gpio1[16]
16 T14 gpmc_a3 mii2_txd2 rgmii2_td2 mmc2_dat2 gpmc_a19 ehrpwm1B_mux1 gpio1[19]
17 A16 spi0_cs0 mmc2_sdwp I2C1_SCL ehrpwm0_synci     gpio0[5]
18 B16 spi0_d1 mmc1_sdwp I2C1_SDA ehrpwm0_tripzone     gpio0[4]
19 D17 uart1_rtsn timer5 dcan0_rx I2C2_SCL spi1_cs1   gpio0[13]
20 D18 uart1_ctsn timer6 dcan0_tx I2C2_SDA spi1_cs0   gpio0[12]
21 B17 spi0_d0 uart2_txd I2C2_SCL ehrpwm0B   EMU3_mux1 gpio0[3]
22 A17 spi0_sclk uart2_rxd I2C2_SDA ehrpwm0A   EMU2_mux1 gpio0[2]
23 V14 gpmc_a1 gmii2_rxdv rgmii2_rxdv mmc2_dat0 gpmc_a17 ehrpwm0_synco gpio1[17]
24 D15 uart1_txd mmc2_sdwp dcan1_rx I2C1_SCL     gpio0[15]
25 A14 mcasp0_ahclkx eQEP0_strobe mcasp0_axr3 mcasp1_axr1 EMU4_mux2   gpio3[21]
26 D16 uart1_rxd mmc1_sdwp dcan1_tx I2C1_SDA     gpio0[14]
27 C13 mcasp0_fsr eQEP0B_in mcasp0_axr3 mcasp1_fsx EMU2_mux2   gpio3[19]
28 C12 mcasp0_ahclkr ehrpwm0_synci mcasp0_axr2 spi1_cs0 eCAP2_in_PWM2_out   gpio3[17]
29 B13 mcasp0_fsx ehrpwm0B   spi1_d0 mmc1_sdcd_mux1   gpio3[15]
30 D12 mcasp0_axr0 ehrpwm0_tripzone   spi1_d1 mmc2_sdcd_mux1   gpio3[16]
31 A13 mcasp0_aclkx ehrpwm0A   spi1_sclk mmc0_sdcd_mux1   gpio3[14]
33 C8 AIN4
34   AGND
35 A8 AIN6
36 B8 AIN5
37 B7 AIN2
38 A7 AIN3
39 B6 AIN0
40 C7 AIN1
41# D14 xdma_event_intr1   tclkin clkout2 timer7_mux1 EMU3_mux0 gpio0[20]
D13 mcasp0_axr1 eQEP0_index   Mcasp1_axr0 emu3   gpio3[20]
42@ C18 eCAP0_in_PWM0_out uart3_txd spi1_cs1 pr1_ecap0_ecap
_capin_apwm_o
spi1_sclk xdma_event_intr2 gpio0[7]
B12 Mcasp0_aclkr eQEP0A_in Mcaspo_axr2 Mcasp1_aclkx     gpio3[18]

Selecting Modes

Using the "everything is a file" sys directory, you can use BASH or whatever to change the mode number for the pin in the NAME column.

echo 7 > /sys/kernel/debug/omap_mux/gpmc_ad4echo 36 > /sys/class/gpio/exportecho out > /sys/class/gpio/gpio32/directionecho 1 > /sys/class/gpio/gpio32/value

If you are using windows, TI has this GUI you can use called PinMuxTool / Pin Mux Utility. The BBB is AM335x r2 based.

The above only works if you're using the older kernel. The new 3.8 based kernel is missing this nifty pin mux feature. However, you can still check what they're muxed at even if you can't change them easily at runtime by looking at

/sys/kernel/debug/pinctrl/44e10800.pinmux/pingroups
root@arm:/sys/kernel/debug/pinctrl/44e10800.pinmux# cat pingroups registered pin groups:group: pinmux_userled_pinspin 21 (44e10854)pin 22 (44e10858)pin 23 (44e1085c)pin 24 (44e10860)group: pinmux_rstctl_pinspin 20 (44e10850)group: pinmux_i2c0_pinspin 98 (44e10988)pin 99 (44e1098c)group: pinmux_i2c2_pinspin 94 (44e10978)pin 95 (44e1097c)group: pinmux_emmc2_pinspin 32 (44e10880)pin 33 (44e10884)pin 0 (44e10800)pin 1 (44e10804)pin 2 (44e10808)pin 3 (44e1080c)pin 4 (44e10810)pin 5 (44e10814)pin 6 (44e10818)pin 7 (44e1081c)group: pinmux_userled_pinspin 21 (44e10854)pin 22 (44e10858)pin 23 (44e1085c)pin 24 (44e10860)group: mcasp0_pinspin 107 (44e109ac)pin 103 (44e1099c)pin 101 (44e10994)pin 100 (44e10990)pin 106 (44e109a8)group: nxp_hdmi_bonelt_pinspin 108 (44e109b0)pin 40 (44e108a0)pin 41 (44e108a4)pin 42 (44e108a8)pin 43 (44e108ac)pin 44 (44e108b0)pin 45 (44e108b4)pin 46 (44e108b8)pin 47 (44e108bc)pin 48 (44e108c0)pin 49 (44e108c4)pin 50 (44e108c8)pin 51 (44e108cc)pin 52 (44e108d0)pin 53 (44e108d4)pin 54 (44e108d8)pin 55 (44e108dc)pin 56 (44e108e0)pin 57 (44e108e4)pin 58 (44e108e8)pin 59 (44e108ec)group: nxp_hdmi_bonelt_off_pinspin 108 (44e109b0)

Check Pin Statuses

root@beaglebone:~# cat /sys/kernel/debug/gpio
GPIOs 0-31, gpio:

GPIOs 32-63, gpio:
gpio-52  (eMMC_RSTn           ) out lo
gpio-53  (beaglebone:green:usr) out lo
gpio-54  (beaglebone:green:usr) out lo
gpio-55  (beaglebone:green:usr) out hi
gpio-56  (beaglebone:green:usr) out lo
gpio-59  (McASP Clock Enable P) out hi

GPIOs 64-95, gpio:

GPIOs 96-127, gpio:


Power Limitations

Be careful about this one, there are some much lower limits than you might be used to

 Pin Type Maximum Voltage Maximum Current AIN 1.8V GPIO 3.3V 4mA - 6mA VDD 3.3 3.3V 250mA VDD 5V 5V* 1000mA * SYS 5V 5V 250mA VDD ADC 1.8V 0? SYS 5V 5V 250mA

* VDD only works when the 5V barrel jack is used

i2c

It is recommended that you use I2C2 on pins 19 and 20 with the /dev/i2c-3 device.

 Mode Name Port Physical Pin Number Block Device I2C1 P9 17 & 18 or 24 & 26 ? I2C2 P9 19 & 20 or 21 & 22 /dev/i2c-3

To check which i2c interfaces are avaible, check

root@arm:~# ls -l /dev/i2c*crw-rw---- 1 root i2c 89, 0 Jun  5 04:34 /dev/i2c-0
crw-rw---- 1 root i2c 89, 1 Jun  5 04:34 /dev/i2c-1

To see what addresses are being used, try the i2cdetect command. In the below example, I have a temperature sensor hooked up to pins 19 and 20 that is using 48. Also note that the UU addresses are being used by the system and are unavailable.

root@beaglebone:~# i2cdetect -y -r 3
0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- UU -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- 48 -- -- -- -- -- -- --
50: -- -- -- -- UU UU UU UU -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --
Attachments:

BeagleBone Internet over USB only

Sure, the BeagleBone and BeagleBone Black come with an ethernet port on them, but why have to get another cable out? You might not even be anywhere near the router. The BeagleBone images automatically do network communcations over USB, as shown by how you can go to 192.168.7.2 from your browser to see the BeagleBone start page and http://192.168.7.2:3000/ to use the Cloud9 editor hosted on the BeagleBone. The problem is that the host computers do not usually relay network traffic to new interfaces. I don't know why not. It would be nice if you could just connect stuff to any connection and it'd always work, but it's not hard to set up NAT and such once you know how to do it. The connection over USB might be slighlty slower than the dedicated connection, since USB is slower and is sharing the connection with things JTAG communication and mass storage. For all I know, though, the ethernet on the BeagleBone is actually controlled by the same USB controller, so it might not be at all different!

On the BeagleBone

ifconfig usb0 192.168.7.2route add default gw 192.168.7.1

On Linux computer:

sudo su#eth0 is my internet facing interface, eth3 is the BeagleBone USB connectionifconfig eth3 192.168.7.1iptables --table nat --append POSTROUTING --out-interface eth0 -j MASQUERADE
iptables --append FORWARD --in-interface eth3 -j ACCEPT
echo 1 > /proc/sys/net/ipv4/ip_forward

On a Windows computer, I would think you could use the graphical Internet Connection Sharing feature.

BeagleBone Security System

Since the BeagleBone (and the Raspberry Pi) is Linux based, and has usb ports, it is actually very easy (and cheap) to make a security camera system. All you need are USB webcams. Just about any will do. I got four for $16 on Amazon. More expensive ones might say they have higher resolution, but what they are actually reporting is the still photo quality, not streaming video quality. Unless you get a USB 3.0 webcam, which would not be supported by either hobbyist computer, it is impossible to stream HD (1080) video, but some might be able to 720. Even if it were possible, it becomes difficult to store so many photos or videos of that size. So keep it cheap, but make sure it is Linux compatible (UVC/V4L), which can be difficult to find sometimes. One major limitation of this kind of system is the cord length limit on USB, which is only 2-7 meters (6-17 feet). It should be possible to get around this limitation with the use of hubs and repeaters. Motion Detection Software Motion is a great system for security systems. It monitors the camera for any motion and saves pictures or video (or both) only when there is something happening, which is great for saving space. Installation (BeagleBone) Motion is actually in the Angstrom package repositories! Why does that surprise me so much? Oh wait. They're for the wrong architecture ARM7a vs ARM7l. Would it work anyway? No idea. Probably best not to try. Ok, so this isn't going to be as easy as it could be. Download the source from the motion homepage by finding a link to it in your web browser and then: opkg install kernel-module-uvcvideo libavformat-staticdevln -s /usr/include/libv4l1-videodev.h /usr/include/linux/videodev.hln -s /usr/include/libavformat/avformat.h /usr/include/avformat.hln -s /usr/include/libavformat/avio.h /usr/include/avio.hln -s /usr/include/libavutil/avstring.h /usr/include/avstring.hln -s /usr/include/libavutil/attributes.h /usr/include/attributes.h wget$URLGOESHEREtar -xzf motion.tar.gz#it will probably tell you the time is in the future.#BeagleBone does not have the correct time. It has no clock.cd motion-3.2.12/./configuremakemake install

After all of that, I never got it to compile. I think it might be because the version of ffmpeg currently in the repo is old, but I'm not sure since this seems to have more to do with uvc.

track.c: In function 'uvc_center':
track.c:587:29: error: storage size of 'control_s' isn't known
track.c:589:24: error: 'V4L2_CID_PRIVATE_BASE' undeclared

If you use an older version of motion (3.2.6), you can get a different error involving jpeglib, but it's no easier to figure out.

This is a very good example of why Ubuntu on the BeagleBone is desirable. The installation process on Ubuntu is as easy as it is for the Raspbian (both are Debian based). So, even though I couldn't get it working in Angstrom, it is still possible to use a BeagleBone for this project

Raspberry Pi Installation

Motion is also in the Raspbian package repositories, which is not surprising since it's basically Debian.

sudo apt-get install motion

Isn't that easy? Why yes. Yes it is.

Configuration

Motion has a very usable configuration file in /etc/motion/motion.conf. Here are some useful configuration options:

width 640height 480framerate 10# Threshold for number of changed pixels in an image that
threshold 1500
# The quality (in percent) to be used by the jpeg compression (default: 75)
quality 50# Use ffmpeg to encode mpeg movies in realtime (default: off)
ffmpeg_cap_new on# Target base directory for pictures and films
target_dir /var/log/security
#break into different folders based on days, not subdivided into hoursjpeg_filename %Y%m%d/camera-%t/motions/%H%M%S-%v%q
movie_filename %Y%m%d/camera-%t/movie/%v-%Y%m%d%H%M%S

# The mini-http server listens to this port for requests (default: 0 = disabled)
webcam_port 8081# Maximum framerate for webcam streams (default: 1)
webcam_maxrate 10# Restrict webcam connections to localhost only (default: on)
webcam_localhost off


Saving movies instead of just images turns out to be surprisingly efficient. For example, a day in my setup yielded 7640 images and only 35 movies, which meant 210MB vs 55MB of storage space. So, to save space, "output_motion off" might be a good change. Saving both kinds of motions (video and stills) at 640x480, 2.3GB could be used on a busy day, but with an average of more like 100MB. Obviously, it will depend on how often things move in your cameras' field of view and what you have your threshold set at. In most cases, you will want a large SD card or maybe even an external USB HDD to store these on.

One really cool feature of motion is that it can stream the webcam image over HTTP as an mjpeg. So, by visiting the BeagleBone's address and webcam_port (ex http://beaglebone.local/8081), you can watch the in a browser from somewhere in your own network. However, if you do port forwarding, or the beaglebone has a public IP, you can keep an eye on things from anywhere in the world. It does not, however, have a way to password protect the stream. So keep that in mind before making it public.

Automatic Cleanup

To make sure that the local storage does not fill up, you can delete old data. This can be done automatically based on age using cron and the find program. The following crontab will search for anything over the specified age (in days) and delete it. Note that this does not guarantee that there will be enough disk space. For example, if a few days with lots of motion occur, it could fill up before influx ages enough.

crontab -e # m h dom mon dow   command
45  1  *   *   * find /var/log/security/ -maxdepth 1 -ctime +145 -exec rm -rf {} \;# delete anything (non-recursively) in /var/log/security older than 145 days

Electronics

Many projects do not actually require much knowledge about electricity. Despite what is learned in places like physics classes, it is almost never necessary to use Ohm's law to calculate voltage, resistance, and current in a circuit. Many of the components that you will use are really self-contained and just need to be hooked up properly. Really, it often boils down to reading specification sheets and documentation. The devices will say what voltage they need and how much current they will draw and all you have to do is make sure it is getting what it needs.

IO Port Expander (MCP23017 and MCP23008)

The MCP23017 and MCP23008 integrated circuits are a great way to add more I/O pins to a microcontroller. They use the i2c standard, so they can share the same serial line with 254 other sensors and even up to 8 other chips of the same exact type.  They are particularly good for a Raspberry Pi because they have higher current capabilities than the Raspberry Pi's GPIO pins. The MCP can supply 25mA per pin and the Raspberry Pi can only do less than 16mA per pin. 20mA is enough to fully power a strong LED, so 16mA may not be enough in some cases. More importantly, through the use of a relatively cheap logic level shifter, many 5V I/O pins can be added to a single serial channel despite the fact that the Raspbery Pi uses 3.3V GPIO and serial.

 GPB0 ↔ • 1 ◡ 28 ↔ GPA7 GPB1 ↔ 2 27 ↔ GPA6 GPB2 ↔ 3 26 ↔ GPA5 GPB3 ↔ 4 25 ↔ GPA4 GPB4 ↔ 5 24 ↔ GPA3 GPB5 ↔ 6 23 ↔ GPA2 GPB6 ↔ 7 22 ↔ GPA1 GPB7 ↔ 8 21 ↔ GPA0 VIN → 9 20 → INTA GND → 10 19 → INTB 11 18 ← RESET SCL → 12 17 ← ADDR2 SDA ↔ 13 16 ← ADDR1 14 15 ← ADDR0

 SCL ↔ • 1 ◡ 18 ← VIN SDA ↔ 2 17 ↔ GP7 ADDR2 → 3 16 ↔ GP6 ADDR1 → 4 15 ↔ GP5 ADDR0 → 5 14 ↔ GP4 RESET → 6 13 ↔ GP3 7 12 ↔ GP2 INT ← 8 11 ↔ GP1 GND → 9 10 ↔ GP0

*The bold pins are required. In particular, it is important to set the RESET pin to high.

GPA#, GPB#, GP# are the GPIO pins. On the 16 pin version, there are two ports denoted by the A and B (PORTA, PORTB).

INTA, INTB, INT are the interrupt outputs that can be monitored by the microcontroller to notify it when inputs change. On the 16 pin variant, there is one for each GPIO port.

 0 1 0 0 ADDR2 ADDR1 ADDR0 Hex Addr. Dec. Addr. 0 1 0 0 0 0 0 0x20 32 0 1 0 0 0 0 1 0x21 33 0 1 0 0 0 1 0 0x22 34 0 1 0 0 0 1 1 0x23 35 0 1 0 0 1 0 0 0x24 36 0 1 0 0 1 0 1 0x25 37 0 1 0 0 1 1 0 0x26 38 0 1 0 0 1 1 1 0x27 39

The ADDR# pins can be set to high or low to change the address by 1 or 0 in the style in the address table allowing for a possible total of 8 different addresses, and therefore allowing up to 8 chips total. Both the 16 GPIO and 8 GPIO pin variants start at 0x20, so mixing the type will not help get more. If you are using more than 128 pins, you might want to consider alternatives like shift registers.

The RESET pin can be used to clear the registers and set it back to its power-on state, but really that isn't very useful since you can always use serail commands. So, usually you will just wire it directly to HIGH (3.3v or 5v) so that it always stay on.

Arduino

There is an Arduino library made available by adafruit on GitHub. Usage is very simple:

#include <Wire.h>
# define BLINKPIN 0# define INPUTPIN 1# define ECHOPIN 13// blinks MCP pin 0 on and off// turns MCP pin 13 on when MCP pin 1 is high or unplugged
void setup() {
mcp.begin();      // use default address 0x20 (0,0,0)

mcp.pullUp(INPUTPIN, HIGH);  // turn on a 100K pullup internally
}void loop() {
delay(100);
delay(100);
}

The major problem with the above code is that the ECHO is not updated until the delays are done. To get by that limitation, something like Metro or Kernel could be used, or simply checking the time yourself. This example was built just to show the bare minimum of how to interface with the MCP, not to show a practical application though.

Raspberry Pi

Adafruit also provies a Python library for the Raspberry Pi, which is also easy to use.

from Adafruit_MCP230XX import *# Use busnum = 0 for older Raspberry Pi's (256MB)
# Use busnum = 1 for new Raspberry Pi's (512MB with mounting holes)
# Set pins 0, 1 and 2 to output (you can set pins 0..15 this way)
mcp.config(0, mcp.OUTPUT)
mcp.config(1, mcp.OUTPUT)
mcp.config(2, mcp.OUTPUT)

# Set pin 3 to input with the pullup resistor enabled
mcp.pullup(3, 1)
# Read pin 3 and display the results#bitshift output, third bit is the output
print "%d: %x" % (3, mcp.input(3) >> 3)

# Python speed test on output 0 toggling at max speed
while (True):
mcp.output(0, 1)  # Pin 0 High
mcp.output(0, 0)  # Pin 1 Low

NPN and PNP Transistors

Introduction

Transistors are incredibly useful devices. My favorite use for bipolar junction transistors (BJTs) is switches. By either applying a high (1) or low (0) voltage to them, the transistors switch from on to off or vice versa. These transistors also can be used for current amplification. They can also be used along side diodes to create logic gates. However, this will focus on the difference between the NPN and PNP transistors.

How to choose between the NPN and PNP transistors

The two transistors can be used to perform the same thing, such as switching, but how to use them differs. Below I explain how both the NPN and PNP function and then depending on your application, you can choose whichever transistor is more applicable.

NPN Transistor

NPN transistors flow current from the collector to the emitter. Generally, the emitter is grounded and the circuit that will be powered on and off is put on the powered collector side of the transistor. It should be noted that although the top part of the circuit may be connected to a voltage, no current actual runs through the circuit until it is connected to ground, which is separated from the circuit by the NPN transistor. The NPN transistor is on when there is a high voltage (1) connected to the base and off when there is a low voltage (0 - generally ground) connected to the base. It is also important to know that the voltage on the base pin is connected to how the transistor is connected in the circuit. The base pin voltage in this configuration is ground, which is likely due to the grounded emitter pin. This is why when the NPN transistor's base pin is then connected to a high voltage, such as 5V, current flows into the transistor and connects the emitter and collector.

PNP Transistor

PNP transistors flow current from the emitter to the collector. Generally, the emitter is powered and the circuit that will be powered on and off is put on the collector side of the transistor connected to ground. It should be noted that the circuit will once again not be powered unless the transistor is in the on position. The PNP transistor is on when there is a low voltage (0 - generally ground) connected to the base and off when there is a high voltage (1) connected to the base. In the case of the PNP transistor, the voltage on the base pin is approximately what the Vcc voltage is. When I tested this with a 5V Vcc, the base pin voltage was approximately 4.6V. This is why when the PNP base pin is connected to ground, current will flow to the transistor, which connects the emitter to the collector.

Cautions

When working with transistors as with all components in circuits, care has to be taken to analyze how the current flows through the circuit. With transistors, it is a little trickier since there are three pins rather than two like with resistors and capacitors. However, as stated previously, they are very useful components. If something is not working the way you expect, I have found that there is generally current flowing into or from a base pin unintentionally.

For a more thorough discussion visit here.

Sensors

Preface

Here is a list of sensors that we have found useful for various projects. Each tutorial for a sensor gives an explanation of what it is, potential uses, and sample code.

GP2Y0D810 Infrared Sensor

Introduction

Infrared sensors are a form of distance sensors. They tend to be more susceptible to inaccuracies. This is because they send out infrared light and wait for the light to tell distance. Certain colors, especially black, absorb some of the infrared light and may return a false reading.

This was tested on a variety of objects that were what would be considered black. A reading was obtained from almost all of the tested objects, although the distance returned varied. There was one black object that the sensor could not detect at all. The moral of this story is do not rely solely on infrared sensors for distance detection. Redundancy is key when working on robots.

For the GP2Y0D810 sensor, Pololu makes a breakout board that has three pins on it: VIN, GND, and OUT.

Schematic

The important thing to note is that the OUT pin goes to an analog pin.

Coding

This sensor was used on a robot that did not want to get too close to objects, so when the analog value hit a given number that meant that the robot was within 10cm of an object on the side that the sensor faced. Knowing the value, the robot would be able to respond accordingly.

Below is the code explaining how the sensor works. The value that is given was found by holding objects over the sensor and lowering them until the built-in LED would light up. The value was found to be consistent.

int irPin = A0;
int sensorValue = 0;

void setup() {
Serial.begin(9600);
}

void loop() {

//check for value of 85 or less for distance testing
if (sensorValue <= 85) {
Serial.println("Too close");
}

delay(1000);
}

This is just a very simple use of the infrared sensor, but an effective one depending on the purpose.

GP2Y0A02YK Infrared Sensor in Real Distance

Communication

Connection

Simply connect the RX to TX and TX to RX on each end of the ArduIMU and whatever you're reading it with.

To just read the output on a linux based controller, simply run the command in bash:

sudo cat /dev/ttyAMA0

Do not use I2C

Do not bother with trying to communicate with it via i2c. Sure, i2c is nice and compact, but the compass on the board is actually using those pins and i2c. As a result, the ArduIMU is in master mode, and you cannot be the master. I wasted a lot of time trying to figure out how to read it. Do not be fooled by the fact that you can see a device on the 1E address, that is the compass. Furthermore, i2c is a little too slow to be used, so even if that wasn't a problem, it would still be a bad idea.

Format

According to the Google Code page, the output format is like this:

!!!VER:1.8.1,RLL:1.12,PCH:-0.07,YAW:34.03,IMUH:253,LAT:499247361,LON:-1193955623, ALT:3525,COG:0,SOG:0,FIX:1,SAT:9,TOW:21230400***

That's probably not what yours looks like though. To see where this comes from, find the source code here for your version, then look at Output.pde. In my version 1.9.1, the format adds slots for analog pins. My ArduIMU v3 outputs something in the format of:

Temp: 63503	Accels: 0	2	27	Gyros: 0	0	0	Mag: 397	0	-482

First of all, those spaces are actually tab characters. Also I have no idea what temp is doing, but it looks useless here since it is just changing randomly. "Gyros" is the change in orientation detected by the gyroscope. So it will say 1 or -1 usually in each - maybe a little more if it's turning fast. The accels and mag outputs are vectors pointing in the direction and magnitude of the pull in x,y, and z. The default output lacks any euler angles, quaternions, or direction cosine matrices which is disappointing.

In all likelihood, the ArduIMU is probably sending you more information than you really want. It may be worthwhile to reprogram it to give you only the information you need. Most of the common choices can be made by editing Arduimu.ino.

After some tweaking, mine now looks like this:

RLL:-7.76,PCH:3.77,YAW:145.72,IMUH:253,ACCX:-0.33,ACCY:-0.67,ACCZ:9.58,


It prints the euler angles, IMU health, and acceleration vector. I also removed anything to do with a GPS. It's fast enough that the Arduino IDE can't keep up with the serial output. It maxes out my processor and lags behind a bit. Hopefully this is not the sensor lagging, but just the extremely rapid displaying.

If you are interested, read how to program the ArduIMU below, then grab my modifications to the stock ArduIMU code at the bottom of this page.

Reprogramming

Wiring the FTDI

 ArduIMU v3 OSEPP FTDI BLK GND GND CTS 5V VCC RX TXD TX RXD ??? DTR

Odds are you really want the Euler angles, quaternion, or rotation matrix to be printed, since that is a lot easier to use quickly. You will need an FTDI cable. I picked the OSEPP one because it has a jumper to choose between 3.3V and 5V, which seems like an awesome feature. I picked that up for around 15on Amazon. I was able to just solder some female header onto my OSEPP FTDI and plug the Arduimu in directly using the group of horizontal pins at the bottom. Also be sure to switch it to 3.3V mode. From what I've read, it seems like it may not matter, really, what the voltage is on some of the lines. SparkFun discuses it on one of their product pages. I'm betting there is some truth to that since there is a 5V pin. Also, depending on the FTDI cable you have, there is a possibility that you might need to press the reset button yourself. The auto-reset feature is apparently somewhat new and will also depend on whether it is wired up correctly. It is also recommended that you power the ArduIMU with something other than the FTDI cable while programming. So, be sure to connect an additional power source to the Vin or 3.3V pins. Makefile From there, you just need to configure the makefile. Run make configure to configure make, then run make upload to compile and upload it. My Makefile looked like this, but I never actually got it to work: BOARD = atmega328ARDUINO_DIR = /usr/share/arduinoTARGET = ArduimuARDUINO_PORT = /dev/ttyUSB0ARDUINO_DIR = /usr/share/arduinoAVR_TOOLS_PATH = /usr/bininclude ../AP_Common/Arduino.mk I also found that you might need to add #define ARDUINO 103 to the code in order to fix a few compile errors. This was probably a sign of some bigger problems though. Arduino IDE It is actually easier to just use the Arduino IDE. Copy the Library folder from the zip of the code you download to your sketchbook Library folder. Open the Arduimu.ino file in the Arduino IDE. Simply select the correct Serial port - on my Ubuntu Linux system it was /dev/ttyUSB0. Then select a compatible board - the Arduino Nano w ATmega328. The programmer is just the standard AVRISP mkII due to the serial interface selected. On windows, the setup process for the FTDI cable may be more in depth. The ArduIMU google code page has some more information on it. You might be better off just looking up your specific FTDI cable first though. With the FTDI cable on my system, you can actually just open the serial monitor and set the baud rate to 38400. I didn't know that at first and was hooking it up to a raspberry pi to see the output. This is a lot easier. Fixing Bugs If you get this error: AP_Common/AP_Common.h: In function ‘int strcasecmp_P(const char*, const prog_char_t*)’:AP_Common/AP_Common.h:108:38: error: ISO C++ forbids declaration of ‘type name’ with no type [-fpermissive]AP_Common/AP_Common.h:108:38: error: ISO C++ forbids declaration of ‘type name’ with no type [-fpermissive]AP_Common/AP_Common.h:108:32: error: expected primary-expression before ‘const’AP_Common/AP_Common.h:108:32: error: expected ‘)’ before ‘const’ Just add this line to the top of Arduimu.pde. Somewhere above the #include statements: typedef char PROGMEM prog_char; I also went around and removed FastSerial and just left it with the regular serial. I'm guessing there was a good reason for making their own, but it was extremely annoying that they had to use the same variable name as the regular Serial object. I couldn't get it to compile due to it. Configuring Output There are a bunch of #define statements in the Arduimu.ino file. Those can be changed to modify a lot of the important features. I had to change just about every one of the settings to get what I wanted. This is the result: // Enable Air Start uses Remove Before Fly flag - connection to pin 6 on ArduPilot #define ENABLE_AIR_START 0 // 1 if using airstart/groundstart signaling, 0 if not#define GROUNDSTART_PIN 8 // Pin number used for ground start signal (recommend 10 on v1 and 8 on v2 hardware)/*Min Speed Filter for Yaw drift Correction*/#define SPEEDFILT 0 // >1 use min speed filter for yaw drift cancellation (m/s), 0=do not use speed filter/*For debugging propurses*/#define PRINT_DEBUG 0 //Will print Debug messages//OUTPUTMODE=1 will print the corrected data, 0 will print uncorrected data of the gyros (with drift), 2 will print accelerometer only data#define OUTPUTMODE 1#define PRINT_DCM 0 //Will print the whole direction cosine matrix#define PRINT_ANALOGS 0 //Will print the analog raw data#define PRINT_EULER 1 //Will print the Euler angles Roll, Pitch and Yaw#define PRINT_GPS 0 //Will print GPS data#define PRINT_MAGNETOMETER 0 //Will print Magnetometer data (if magnetometer is enabled)// *** NOTE! To use ArduIMU with ArduPilot you must select binary output messages (change to 1 here)#define PRINT_BINARY 0 //Will print binary message and suppress ASCII messages (above)// *** NOTE! Performance reporting is only supported for Ublox. Set to 0 for others#define PERFORMANCE_REPORTING 0 //Will include performance reports in the binary output ~ 1/2 min Furthermore, I think it is weird that they would have an option to print the magnetometer, but not the accelerometer. It seems like acceleration would be a lot more important for a controller, since the magnetometer's information, I assume, is already built into the orientation output. Modifying the Output To add the acceleration information, I just modified Output.ino (line 61 to 68) #define ACCELCONVERSION 0.0023147712Serial.print("ACCX:");Serial.print(Accel_Vector[0]*ACCELCONVERSION); Serial.print(",ACCY:");Serial.print(Accel_Vector[1]*ACCELCONVERSION);Serial.print(",ACCZ:");Serial.print(Accel_Vector[2]*ACCELCONVERSION);Serial.print(","); The ACCELCONVERSION constant was chosen by expermentation to convert to the output to m/s2 using the following method: 1. Print the values of the Accel_Vector 2. Leave the ArduIMU on a flat level surface 3. Take a few samples of the acceleration on the z axis (Accel_Vector[2]) 4. ACCELCONVERSION = 9.81 / SampleAverage Repeat the process, if necessary, until the output is correctly calibrated to the known gravitational constant. It is perhaps better practice to instead do the conversion on the recieving device, since the values would be more compact and accurately sent over serial. On the other hand, it makes the ArduIMU more easily accessible if the units are known. To convert the acceleration data on the reading device, the proceedure is the same. Parsing the Serial Input While you could read this sensor with an Arduino, it already is an Arduino. Furthermore, the mere fact that you're using it probably means you want to analyze a 3D system. You're probably going to need some more firepower. Something like a Raspberry Pi, or a BeagleBone. A Raspberry Pi processor is at least 1000 times faster than an Arduino, and a BeagleBone Black is at least twice as fast as a Raspberry Pi and has more pins. With these faster devices, you get to use a higher level programming language like Python or Node.js. Both will run Python, so it is a good choice for speed and portability. Attachments: Joystick Introduction Joysticks have become a common tool among various devices, such as gaming controllers. They can be an interesting addition to projects as well. Joysticks are fairly simply components that use two potentiameters to give the readings from two axes. They may also include a button to see if the user has clicked the joystick. Schematic Below is a schematic showing how the joystick connects to an Arduino. As stated previously, a common joystick will use two rotating potentiameters and a button. The potentiameters are analog while the button is digital. Code The following code shows how to read the various components of the joystick. int verPin = A0; int horPin = A1; int selPin = 2; void setup() { pinMode(selPin, INPUT); digitalWrite(selPin, HIGH); } void loop() { int verPos = analogRead(verPin); int horPos = analogRead(horPin); boolean selBtn = digitalRead(selPin); } Getting the information from the component is really simple, but a lot of fun projects can be done with joysticks. Wireless Communication Preface A mobile robot shouldn't be hindered by power cables and data connections. So, when making a mobile robot, it is often necessary to communicate with it wirelessly. Many forms of wireless communication are still, essentially, serial. So, converting a project from being tethered by a USB to being completely wireless is simply a matter of getting a good battery, and the right wireless accessories (you'll need two ends). XBee Configuration Introduction XBees are one form of wireless communication. They use radio frequency to communicate over long distances (from 100m to over 1500m.) They do have issues transmitting through walls and through obstacles, but that is common to many types of wireless communication. There are two main types of XBees: Series 1 and Series 2 . Series 1 XBees do not say that they are Series 1 on them, but that is one way to determine that they are Series 1. Series 1 is generally easier to use and configure. It is also faster than Series 2. The advantage of the Series 2 XBees is that there is a lower current draw. This tutorial will go through the configuration of Series 1 XBees. Configuring the XBees The figure below shows what a typical XBee looks like. Before getting XBees to communicate with each other, it may be necessary to configure. This tells the XBees which channel they will send or receive data from and which XBee they are communicating with. Configuring can be done easily with the use of a software called X-CTU . The X-CTU program can be found under Diagnostics, Utilities and MIBs . There are two diff erent boards that can be used for confi guration. The XBee Explorer USB board is available through Sparkfun . The SainSmart XBee Shield module , as seen below, can also be used to con figure XBees with the use of an Arduino. Note: If the XBee Shield module is being used, put your Arduino in reset, which means run a wire from reset to ground as seen below, and make sure the jumpers on the shield are set to USB. Put the shield on the Arduino. Plug either the Arduino and shield or the Explorer board into the computer and then start the X-CTU program. The program should be able to open up and display a screen similar to the one below. Notice how it recognized the product being used. It should be noted that this is the PC Settings tab. In this tab, there should be a Test/Query button on the right. An example of the screen print out can be seen below. From this screen, the Serial Number High (SH) and Serial Number Low (SL) can be found for the Arduino. This can be done by breaking apart the Serial Number. Each SH and SL can be eight hexadecimal digits long; however, the SL will be eight long and the SH can be shorter. For example, the above figure shows a SH of 13A200 and a SL of 404AC735. Go to the Modem Con guration tab and select the Download new versions button. Wait for the download to fi nish and then select the Read button. This will read some of the data in the XBee, as seen below. If the XBee has not been con figured before, it will not read the SH or SL from it, so that information must be obtained from the Test/Query screen. Repeat these steps with the other XBee and make sure to know which SL and SH belong to each XBee. Now configuration can begin: 1. Select one of the XBees, which will now be referred to as XBee 1, and plug it back into the board; the other XBee will now be referred to as XBee 2. 2. Read XBee 1 to make sure it has the expected SL and SH values. This should also set the Modem to the Modem of the XBee. 3. Change the Destination Address High (DH) of XBee 1 to the SH of XBee 2. 4. Change the Destination Address Low (DL) of XBee 1 to the SL of XBee 2. 5. This is not necessary to change, but in order to avoid interference with other XBees, it would be prudent to change the Pan ID (ID) of the XBee as well to a number below FFFF, such as 2222. 6. Select Write after all the changes have been made. 7. Unplug XBee 1 and plug in XBee 2. 8. Read XBee 2 to make sure it has the expected SL and SH values. This should also set the Modem to the Modem of the XBee. 9. Change the DH of XBee 2 to the SH of XBee 1. 10. Change the DL of XBee 2 to the SL of XBee 1. 11. If you changed the ID of the XBee 1, make sure you change the ID of XBee 2 to the same value. 12. Select Write after all the changes have been made. The following figure gives a graphical representation of this. The two XBees should now be configured to communicate with each other. This means that coding to connect the two may now be done and the wireless communication is ready to go. XBee Communication Introduction XBees are a very simple way to enable wireless communication. Using wireless communication will expand the possibilities of a project, and is practically a necessity for a robot. Two types of XBee communication that will be discussed are Arduino-Arduino communication and Arduino-Computer communication. XBees cannot both send and receive data at the same time. If caution it taken, data should not be lost due to this fact. Arduino-Arduino Communication If the Arduino shield is being used, the jumpers should be set to USB mode when programming the Arduinos and then should be set to XBee mode when the programs are run. Coding with XBees is simple because they can simply be coded using the familiar serial code. To send from an XBee: Serial.print("Send to other XBee"); To receive from an XBee: int incomingByte;if (Serial.available() > 0) { incomingByte = Serial.read(); Serial.print(incomingByte); } Arduino-Computer Communication The above code for sending and receiving data from an XBee is valid for the code on the Arduino. If an Arduino with a shield is used to connect to the computer, the code put on that Arduino is a simple blank sketch: void setup() {}void loop() {} The blank sketch bypasses the microcontroller and allows the data to flow through to the computer. For the XBee shield that is connected to the computer, the jumpers should be placed on USB mode since the data is going to be sent through the USB to the computer. The data coming through can then be seen in the serial monitor. The data sent from the serial monitor will then be sent through the XBee to the other one on the Arduino. If the serial monitor is not an attractive option, python code can also be used to handle the serial coming through. Creating a GUI may be a best option to handle the serial coming into the computer. Programming Preface It turns out, making robots requires a lot of programming. The more autonomous, the more advanced the program. Here are some conceptual lessons in programming. Odds are you'll find them useful when programming for a robot. Introduction to C++ Programming Introduction Programming is becoming more useful in a variety of fields. There are a lot of uses, but we are most interested in robotics applications. Microcontrollers like the Arduino are programmed in C++, which is undoubtedly the most widespread language. It is powerful, fast, and easier to use than some earlier languages. However, it is not the easiest language to learn. It has a very strict syntax and the errors can be hard to understand. It is still worthwhile to learn due to its usefullness. If you are just interested in learning programming in general, I highly recommend looking at Codecademy, which is an excellent interactive environment for learning for the first time. Of their courses, Javascript is most similar to C++, but Python is the easiest and most powerful choice. The Basics Programming is actually quite simple. There are really only a few things that you need to know to get started. • Data is stored in "variables" • The right hand side of an equals sign goes into the storage with the name at the left • There are different kinds of variables that contain different kinds of information • A program is executed top down • Each line is terminated by a semi colon • Comments are ignored ( lines that begin with two slashes: // ) • There are three fundamental actions that alter the top-down flow: • Conditions: do something only if something else is true • Loops: do something repeatedly • Functions: do a group of things and get a result Try It Yourself Set up a Development Environment You need a place to code! Code::Blocks is a good place to start, but there are dozens of options. Microsoft Visual Studio Express is actually free to use, but there are free-er (open source) options too. To install Code::Blocks, go here and choose the mingw-setup.exe. The mingw is important because it includes a compiler, which turns the program that you can write and read into something that your computer can actually run. Install the program like you would any other. Use the Development Environment Now get started! Run Code::Blocks. Make a new source file (File > New > Empty file). Put this simple program in there. #include <iostream>using namespace std;int main() { // anything preceeded by a // is a comment and ignored by the computer // code goes in between the above and below { and } cout << "HELLO WORLD!"; //shows "HELLO WORLD!" in a command prompt} Be sure to pay attention to things like semi colons and brackets. It won't work if you miss one. All this program does is print out the words HELLO WORLD to the terminal or command prompt whenever it is run. Try it out! Hit the green button "Run" triangle at the top of the Code::Blocks to compile and run it. Fundamentals of Programming These are the five things that you need to know to program, that's all! 1. Variables are places you store data 2. Operators do things to data 3. Conditions check data, and do something if it is a certain way 4. Loops let you repeat actions 5. Functions let you group actions together so you can re-use them and return a result of those actions Variables Variables are not at all like the variables you find in math. These are just named places you put information. You can change the contents of what's at a name, which is what "varies" about it. You can only store a few kinds of information, and they are: • int: An integer can hold a whole number • char:A character can hold a letter or symbol • float: A floating decimal point can (inaccurately) hold really large and really small numbers (and decimals) First, you need to declare the variable. You start by saying the type of data it can contain. When this is done in C++, it is uninitialized - meaning that you have no idea what it contains. You might want to assume, for example, that a number starts at 0 when you declare that you want to use it, but you have to explicitly say that. Then, you assign contents to the variable. The contents can be pre-defined by you, or you can get the contents of another variable, or even read it in from somewhere else. Arrays All variables can be be arrays. An array is a series of variables put next to each other. You specify the array with the array's name, and which item in the list of its variables you want with a number in brackets after it. The first item in the list is at the number 0. You have to say how large an array is when you declare it. An array with its index behaves exactly the same as a variable would int numbers[3]; // declare the array (list) of integers (whole numbers)numbers[0] = 100; // fill the first item in the list with a 100numbers[1] = 200;numbers[2] = 300; // fill the last item in the list with a 300 Swap Example Swapping variables is an excercise of the very important concept of storage and variables. Imagine you have two cars in a parking lot you want to swap parking spaces with. You're the only valet and you want to swap the two cars so they match colors with the other cars because you're bored. In order to swap the cars, you'll have to move one car to a third parking space temporarliy while you move the other into the newly vacated space. It's a similar solution to a slightly different dilema. If you were to try to swap directly (without a temporary) with the cars, you would smash one into the other, but in a program you would end up two copies of the same data. Start by declaring two variables you want to swap, and a temporary variable. Then assign something different to the two variables. Store the contents of one of those into the temporary. This is extremely important because otherwise the contents of "first" will be lost in the next step, which moves the contents of "second" into the "first" variable. Finally, the temporary variable moves the former contents of "first" into the "second" variable. Swap IntegersSwap FloatsSwap CharactersSwap Array Elements //declare integers int first = 100; int second = 200; int temp; //next shift data // Step 1 temp = first; // Step 2 first = second; // Step 3 second = temp; //declare floats float first = 1.0; float second = 2.0; float temp; //next shift data // Step 1 temp = first; // Step 2 first = second; // Step 3 second = temp; //declare charschar first = 'd';char second = 'c';char temp;//next shift data // Step 1 temp = first; // Step 2 first = second; // Step 3 second = temp; int num[2];num[0] = 100;num[1] = 200;int temp;//next shift data // Step 1temp = num[0]; // Step 2 num[0] = num[1]; // Step 3 num[1] = temp; As you can see, it is the same proceedure to swap the contents of variables, regardless of data type. Operators An operator is a letter or couple of letters that just say "do something" to a variable. For example, a + sign is an operator that says add two numbers. There are actually not that many operators. Operators do very simple actions. More advanced actions can usually be broken down into a series of these simple actions. Don't worry, you don't have to remember it all at once, but they are fairly intuitive. • Storage • = The assignment operator copies the contents at the right into the variable at the left. • Math - modify the data • +, -, *, / all perform math operations the way you would expect • ++ and -- increment or decrement a variable by 1 • Really, number++ is just a shorthand for number = number + 1 • += and -= are shorthand for addition and subtraction then asigment • Again, number += 10 is just a shorthand for number = number + 10 • Logical - Checks something about the data • == The equivelence operator checks to see whether the contents of the right and left are the same • Be careful not to confuse it with the assignment operator = • >, <, >=, <= all check for inequalities • ! also called "not" inverts the condition, making a false into true, and a true into false • &&, || also called "and" and "or" respectively are ways to check multiple conditions at once Operator Usage Example // declarationint number = 1; // create space for and store a whole number: 1// arithmeticcout << number; // prints 1cout << number + 2; // prints 3 (1 + 2 = 3)cout << number; // prints 1. "number" did not change! Nothing was assigned;// assignmentnumber = number + 2; // add 1 to 2, then assign that result into numbercout << number; // prints 3. "number" changed! It was assigned a new value// incrementnumber++; // adds 1 to the former contents of number (3)cout << number; // prints 4 (3 + 1 = 4)// logical operationscout << number == 4; // prints a 1, which means true. "number" does equal 4.cout << number > 4; // prints a 0, which means false. Number is not greater than 4 Conditions Conditions, as the name suggests, will check to see if something is true, then react based on that information. Conditions are used in if statements, and evaluated in loops (more on that later). They are either true or false. Use the logical operators to construct your conditions. You can check for equalities, inequalities, and chain these conditions together with and (&&) and or (||) operators. An if will only execute the code within its {brackets} if th condition is true. An else if's code will only get executed if the preceeding "if" was false and it's condition is true. An else's cod will only be executed if the preceeding if and else ifs are all false. Guessing Game Example // Ask for a letter from the user.cout << "I want to play a game. I am thinking of a letter a through z. Guess: ";char letterRead; // declare space for an charactercin >> letterRead; // read input for the command prompt and store it in letterRead// use a condition to see if their guess was correct// note the use of the equivelence checking operator (==), not assignment (=)if ( letterRead == 'm') { // m was the correct letter cout << "Correct! You win!"; }// if the character is after 'z' or it is before 'a'// then the character was not a lower case letter a through zelse if ( letterRead > 'z' || letterRead < 'a') { cout << "That was not a letter..."; }// the character was a letter, but it was not the correct letterelse { cout << "Wrong. You lose.";} Loops Loops run code on repeat until a condition says "stop". char continue = 'y'; // the first time, the loop will run since it starts with 'y'while ( continue == 'y' ) { //do something here until the user says 'n' cout << "Continue? (y/n)"; cin >> continue;} Most loops simply count a number by one so you can go through all the possibilities in a range because loops are most useful for doing something to all of the elements in an array. As a result, a shorthand has been made. Compare: While LoopFor Loop int numbers[10];int index = 0;// loop through numberswhile ( index < 10 ) { cout << numbers[i] << '\n'; index++;} int numbers[10];// loop through numbersfor ( int index = 0; index < 10; index++ ) { cout << numbers[i] << '\n'; } Both loops essentially do the same thing. They print the random, uninitialized contents of the "numbers" array with a newline ('\n') at the end of each element. Functions Functions group operations into a name. You run the operations by saying the name of the function followed by (). You can give the function parameters by passing them between the parenthesis. Maybe most importantly, a function returns the results of its group of actions once it is done. Note tha main is a function. It is run by default when you run the program. It also is an int. The value returned by main is actually an error code. int myPow(int base, int exponent) { // powers of 1 and negative powers will return 0, regardless of the base if ( exponent <= 0 ) { return 1; } int result = base; // create a place to store the result //multiply the result by itself "exponent" number of times for( int i = 1; i < exponent; i++) { result *= base; } return result; //return the product of the exponent}int main() { cout << myPow(5,0); // prints 5^0, which is 1 cout << myPow(1,5); // prints 1^5, which is 1 cout << myPow(2,4); // prints 2^4, which is 16 cout << myPow(2,5); // prints 2^5, which is 32 cout << myPow(3,3); // prints 3^3, which is 27 return 0; // there was no error} Conclusion Congradulations! If you understood most of this, you are now qualified to do quite a few awesome things with an Arduino. Check out our tutorials for tricks with Arduino and using sensors with an Arduino. There is still more to know, but it gets easier from here. In larger programs you will need to worry about where a variable can be accessed from. Also, classes and structures help you organize your data and are extremely powerful when you know how to use them. Data Storage Analogy Storing data on a computer is a lot like storing things in a warehouse. If you keep track of where you put things well enough, it shouldn't matter how much stuff you have stored. Imagine an empty warehouse. If you store something in it, it doesn't really matter if you keep track of it because it's easy to look for it again. If the warehouse were full, you better keep track of where you put your stuff or you'll have to look everywhere for it. In a warehouse, you would probably write down an isle number, a shelf number, and maybe a pallet number. This way, you don't look through all the things, just go directly to the right place. Warehousing Techniques Unindexed Storage (left), Indexed Storage (right) So, by keeping records of stuff as it comes in, you reduce the time it takes to look for it later. It is like what keeps your computer from getting slower when you add files to it. Your file system is the guy in the warehouse putting your files somewhere, and keeping track of where it should be so you can find it again quickly. This is how Google can search the entire internet in just milliseconds - by using a process called indexing. More data doesn't have to be slower. This is why it is important to understand how to store your data efficiently. Linked Lists A lot of the time, you have a specific order to things, but might want to be able to add or remove stuff at the beginning or in the middle. With an array, you would have shift the contents around to keep it in the right order. With a linked list, you just change a few pointers to change the order. There are two main kinds of linked lists: queues and stacks. It's actually pretty easy to remember which is which. A queue is like the line at the grocery store (which in Britain, is actually called a queue), and a stack is like a stack of trays. A queue is First In First Out (FIFO). Things are handled in the order they are receieved. This is extremely useful for things like buffers. A stack is Last in First Out (LIFO). It's mostly useful for coming back to things if you get interrupted or retracing your steps. The two are extremely similar in concept and implementation, but a queue is more common and more useful. A lot of programming languages and environments have pre-built versions of both these which are nice and reliable. Some examples of queue libraries: Python, C++ STL, and Arduino C. These queues are great because they dynamically expand at runtime, so they use only as much space as they need. Using a Queue Push: New things can be added to the end of the queue with a queueName.push( newThing ) Pop: Once there are things waiting in the queue, you get the next one in line out by saying: value = queueName.pop() This both stores the value of the next one in line to the variable at the left, and removes it from the list, so be careful not to accidentally remove something before you're really done with it. Peek: If you don't want to delete the next thing waiting, but still want to see what it is, you can take a peek at it with value = queueName.peek() Indexing An index is like the index at the front or back of a book. You have a condensed table of things you might look for and a place to jump to. Indexes are great for speedy searches through data. The problem is that they require the data to be unique - otherwise you wouldn't know which place to jump to. You could try having a list of places to jump to, but at that point it gets complicated and you lose a lot fo the speed benefit that makes indexing so great. If you find yourself considering indexing to effectively organize your data, you might want to consider using a database instead. If you want to keep it light or do it yourself, you may need to implement a hash table. A hash table is a way to look things up in constant time - which means it takes the same amount of time to find something no matter where it is. Databases In general, you will probably not be using a database on a robotic system. Many of the existing database applications would simply not work on an arduino. You could, however, put one on a raspberry pi. It might be easiest to think of a database like a spreadsheet. Each column stores a specific kind of information. Unlike a spreadsheet, each row usually has a unique identifier, which can be used as the index. An index can be quickly found in the table. These are particularly useful for "merging" tables (the operation is called JOIN). Databases are powerful tools for filtering complex data, and continue to be efficient on larger scales. An example of potential use in a robot is that you could receive sensor readings with a raspberry pi, and store them in a database for analysis. Unless they data needs to be accessed during operation, it might just be easier to store the data to a file in a Comma Seperated Value sheet (CSV), which could then be opened in a spreadsheet program. LaTeX Introduction LaTeX is a typesetting system. It's an easy way to make very professional looking papers. In fact, many academic books were written in LaTeX. You can usually tell by looking in the first few pages. Somewhere it might say "Typeset in LaTeX". LaTeX cannot really help you build a robot, but if you are building a robot either professionally or academically, you will need to present your project in a technical and professional manner with a well-polished document. LaTeX basically takes a plain text file with special syntax and compiles that syntax into a well-formatted PDF. Installation From anecdotal experience, the best and most common way to write LaTeX documents is Texmaker. Other LaTeX editors exist, but they all use the same LaTeX engine, so there really is not that big of a difference between them. Some have different ways to preview the document or wizards to make more complex features. Really, all you need is a plaintext editor and a command prompt, but an editor provides a more streamlined experience. The installation is somewhat large - about a gigabyte. On Windows and Mac it is a multi-step process to install the LaTeX editor and the compiler. On Ubuntu simply run: sudo apt-get install texmaker Using Texmaker Really, all you need to do is make a new document, add some bare minimum structure to the document, and hit the F1 key on your keyboard or the "quickbuild" arrow at the top. Most of the other buttons are just there to help you find more features of latex. For example, there is a symbol library in the left panel if you click the buttons on the far left. There is also a tabular wizard that is extremely helpful for making tables. Demo Tex Document Here is a minimal document that should explain the important features when first learning LaTeX. The various commands will be explained below, but this simply makes a title area, a section, a paragraph, a subsection, a paragraph, and an image. The image to the right is the finished product once it compiles. As you can see, the default LaTeX article document class has large amounts of whitespace. You can override this, but it looks pretty nice the way it is. Take note of how nice the equations look, and the minimal amount of work it takes to get them to look that way. The challenge is in learning the syntax, but it is definitely worthwhile since it is so easy and produces such great results. Another important feature of LaTeX is how it can reference things within the document. For example, by using the section command, you not only style the element on the page, but also make a reference so that a table of contents can easily be made. Also, figures and tables can be easily referenced from within the document by name, number, and page number. A list of figures and tables can also be easily added. Adding images is probably the hardest part of using LaTeX. It is hard to beat the drag and drop ease of adding an image to a modern word processor. In LaTeX, the image has to be in the same folder as the document. Actually inserting it into the document in a certain place occasionally yields unexpected results. Code to Generate Demo Document \documentclass[12pt]{article} %the standard page format \usepackage{amsmath} %math stuffs \usepackage{graphicx} %embed image \DeclareGraphicsExtensions{.pdf,.png,.jpg} %embedabble types % set page margins \usepackage[top=1.1in, bottom=1.1in, left=1.27in, right=1.27in]{geometry} % remove the numbers in front of sections \setcounter{secnumdepth}{0} \begin{document} \title{Title Goes Here} \date{February 22, 2013} \author{Your Name\\} \maketitle \section{First Section Name} Lorem ipsum dolor sit amet, consectetur adipiscing elit. In non pharetra nunc. Etiam rhoncus ornare laoreet. % a math environment, with the ability to align to &s and equation numbering \begin{align} E &= mc^2 \\ m &= \frac{m_0}{\sqrtablest{1-\frac{v^2}{c^2}}} \end{align} \subsection{A Sub Section} Aenean in erat lacus (Figure \ref{robohand}). Suspendisse nec dui vitae lacus viverra facilisis. Sed aliquam erat in augue scelerisque non consectetur mauris faucibus. % add an image inside a figure \begin{figure}[here] \centering \includegraphics[width=1.5in]{robothand.jpg} \\ \caption{A Robot Hand} \label{robohand} \end{figure} % demo a matrix \begin{align} R_z &= \begin{bmatrix} 1 & 0 & 0 \\ 0 & 1 & 0 \\ 0 & 0 & 1 \end{bmatrix} \end{align} \end{document} Formatting Commands Sectioning Chapters, Sections, and Subsections can be used to give your document hierarchy. This hierarchy can provide visual seperation and be used in a table of contents. Their commands are: \chapter{Chapter Name}, \section{Section Name}, and \subsection{Subsection Name} Tables If you are using Texmaker, start by using Wizard > Tabular. \begin{tabular}{l|cc} name & attribute & equation \\ \hline square & a &x^2$\\ cube & v &$x^3\\ \end{tabular}  The above code will create a 3x3 table. According to the second part of the begin command, there are three columns. The first one will be left aligned, the second two are center aligned, and there will be a border between the first and second column. There will also be a horizontal border between the first and second row due to the hline command. Note that it is possible to use the inline math environment in a table. Figures Figures typically contain images, as shown in the demo above. They can also be labelled and referenced in the body of a paragraph. Figure placement can be a challange. Usually, a you will want the figure to go where it is in your code in relation to the paragraphs, so you will usually want to use the "here" or [h] placements. However, sometimes LaTeX will decide on a more 'optimal' placement which isn't. Sometimes this can be overcome by using an exlaimation point [h!]. Figure References Again, according to the demo above, all that is required is that the figure be labelled with the \label{labelname} command, and then referenced with the \ref{labelname} command. Table of Contents Making a table of contents is easy. Just use chapters, sections, and subsections as necessary in your document, then right after your title add a "\tableofcontents" to the following line. I also apply some extra features to my table of contents with some packages. It is easy to add links to the section labels on the pdf so a viewer can jump directly to a chapter, section, or subsection. I also like to have dots going from the label at the left to the page number at the right. On the full 8x11 sheet of paper, it is otherwise hard to line up which label goes to what number. %make Table of Contents link to pages\usepackage[pdfhighlight=/N,linkbordercolor={1 1 1}]{hyperref}\hypersetup{ colorlinks=false, %set true if you want colored links linktoc=all, %set to all if you want both sections and subsections linked linkcolor=black, %choose some color if you want links to stand out}%add dots to table of contents \renewcommand{\cftsecleader}{\cftdotfill{\cftdotsep}} Spacing \vspace{} and \hspace{} are ways to add vertical and horizontal space respectively Math Environment Entering the Environment Inline: To use a quick, inline math environment inside of a paragraph, just use the symbol. Example:

Here is inline math $x^2$. It is shown inside the rest of this paragraph.

Multi-Line: There are several ways to use a mult-line math environment. The most powerful is the align environment. It can be used with a \begin{align} and an \end{align}. As shown in the demo above, you can align parts of the equation (usually the equals) between lines.

LaTeX Math Symbols
NameValueLaTeX Command
Alpha α \alpha
Beta β \beta
Delta δ \delta
Delta Δ \Delta
Pi π \pi
Gamma γ \gamma
Rho ρ \rho
Tau τ \tau
Theta θ \theta
Psi Ψ \psi
Phi Φ \phi
Omega Ω \Omega
Sigma Σ \Sigma
Degree ° ^\circ
Brackets [] \left[ \right]
Parenthesis () \left( \right)
Fraction \frac{num}{denom}

Symbols

These symbols only work in the math environment. So, if you want to use them in the paragraph of your text, use the inline math environment .

Obviously, for the greek letters, all it takes to use them is to remember how to spell their name. Also, capitalizing the first letter of the name makes the letter the capital.

The sigma letter should not be used to make sums. There is a special command called sum. It can be used like this:

\sum\limits_{n=1}^9

The brackets and parenthesis are special in the math environment because they will grow larger as their contents become larger.

The fraction command seperates the fraction vertically similar to how you would write it. A frac takes up more vertical space than its surroundings so that the contents can be the same height. If this is not desired, you can use dfrac, which could be useful if you only wanted to say 1/2 instead of a having a longer numerator and denominator or if the fraction is inside of a matrix.

Subscripts and Superscripts

It is extremely easy to remember how to do subscripts and superscripts in the math environemnt. Simply use a ^ for superscript and _ for a subscript. The letter following the ^ or _ will be used as the script. If you want more than one letter in that space, you can wrap it in curly brackets {}. So, for example:

$x^2 \\ x^{1.5} \\ %superscript (exponents)x_0 \\ x_{start} %subscripts$

Inserting Code

There is a way to get LaTeX to essentially syntax-highlight and line-number code. Use the package listings. It has a bit of setup in the header. The result looks better, but it is difficult to copy and paste the code from the PDF into a text editor - which could be problematic.

Setup
\usepackage{color}
\usepackage{listings}
\lstset{ %
language=C++,                 % choose the language of the code
basicstyle=\footnotesize,     % size of the fonts that are used for the code
numbers=left,                 % where to put the line-numbers (left / none )
numberstyle=\footnotesize,    % font size used for the line-numbers
stepnumber=1,                 % lines between two line-numbers. (1=all numbered)
numbersep=5pt,                % how far the line-numbers are from the code
backgroundcolor=\color{white},% choose the background color.
showspaces=false,             % show spaces adding particular underscores
showstringspaces=false,       % underline spaces within strings
showtabs=false,               % show tabs within strings (add underscores)
frame=single,                 % adds a border/frame around the code
tabsize=2,                    % tabsize in spaces
captionpos=b,                 % sets the caption-position to bottom
breaklines=true,              % sets automatic line breaking
breakatwhitespace=false,      % automatic breaks should only happen at whitespace
escapeinside={\%*}{*)}        % if you want to add a comment within your code
}
Usage
\begin{lstlisting}
void setup() {    Serial.begin(9600);}void loop() {    Serial.println("HELLO WORLD");    delay(1000);}
\end{lstlisting}

Micro Typography

The microtype package applies some really subtle changes to the spacing and styling of the letters. If you compare side by side, the most noticable change is the alignment of paragraphs to headings looking more straight. It has some more advanced features, but it looks good even just keeping it simple:

\usepackage{microtype}

Presentations

It is actually possible to use LaTeX for presentations. PDF's actually work fairly well for slideshows since most PDF readers have a fullscreen slide viewer. Making a presentation in LaTeX using beamer requires more rigid structuring than a document, but still lets you use the same packages and interface that you are accustomed to in documents.

Unlike LaTeX's article document class, beamer does not have any particularly pleasant default styles, so the advantage to using LaTeX instead of an office suite isn't as clear for presentations as it is for documents.

HTML Introduction

Introduction

HTML is the language that your browser reads when it shows you a webpage. It is a variant of XML.  It makes the actual content that you see, but also can contain visual styling information (typically in the form of an external CSS file) and also can have an in-browser (client-side) programming language called JavaScript.

Bare Minimum Example

<!DOCTYPE html><html>
<title>Minimal</title>
</head>  <body>    <p>Hello World!</p>  </body></html>

Tag Structure

Tags are put on either end of something to describe the content between the tags. Since HTML is visual, think of a tag as a box drawn around whatever is inside of it. The outermost tags are <HTML>, <HEAD>, and <BODY>. The <HTML> tag simply says that the contents are HTML. It is the very outermost box on the screen. The <HEAD> tag is invisible. It summarizes the contents (like title and keywords) and also lists files the page needs like stylesheets and scripts - both of which can alternatively be embedded into the actual HTML file if desired instead of being a seperate file. The <BODY> tag is where the actual content that you see on in the browser window goes. It can contain images, text, and other containers.

Basic Tags

<p> - Paragraph

Paragraph tags are useful for providing that spatial seperation between paragraphs. To make a new line, use the self-closing <br /> tag. However, a paragraph is not a line break. the distance between the paragraphs is often a ratio of the line height, like 0.5 lines or 1.5 lines. In print, paragraphs also are indented - a style that can be modified with the text-indent CSS property. So, separating paragraphs by using a separate set of tags more flexible than using some number of line breaks.

<img /> - Image

The image tag is self-closing, which is why it requires the trailing slash. The URL of the image goes in the "href" attribute, and the alternative text if the image cannot be loaded goes in the "alt" attribute.

<img src="http://imgs.xkcd.com/comics/interblag.png" height="432" width="400" alt="An XKCD comic about blog names" />

<strong> - Bold

The strong tag makes text bold. Also, the <b> tag can be used, but it is considered outdated for some reason. Example:

<p> ... to <strong>boldly</strong> go where no man has gone before!</p>

<em> - Italics

The emphasis tag makes text italicized. The <i> tag can be used to make italics, but is also weirldy obsolete. Example:

<p><em>Emphasize</em> makes italics for some reason</p>

Lists

Lists are occasionally used in the body of text for readability, but in websites they are more commonly used for hierarchical (multi-level) navigation. As a general rule, lists should be incomplete sentences and not end with a period. At the very least, the sentence completeness should be consistent throughout the list.

<li> - List item

To make a single list element, wrap some text with <li> tags. This element must be within a list container. The type of container will decide whether there should be bullet points or numbers in front of the list item.

<ul> - Unordered list container

An unordered list element contains list items that have no particular order. This is the most common type of list. The default style applies a different kind of bullet point for each tier of the unordered list.

<ol> - Ordered list container

An ordered list element contains list items that must be in a particular order. it is primarily used for procedural lists that describe a chronological process (a step by step) or it can be used for rankings (a top 10).

The starting number can be chosen by the start attribute ex: <ol start="10">

Example Result

• Discover that it is easy
2. ???
3. Profit

Example Code

<ol><li>Follow Tutorial  <ul>    <li>Discover it is easy</li>    <li>Tell friends</li>  </ul></li><li>???</li><li>Profit</li></ol>

Tables

The easiest way to learn to make a table is by example, but first here is a quick description of all the table related tags:

• <table> - the container for the whole table
• <thead> - the top area of the table (for categories)
• <th> - a table heading cell
• <tbody> - the main area
• <tr> - a table row
• <td> - a table cell
• <tfoot> - the bottom area (for totals)
• <caption> - a caption or title for the table

Example Result

Sample IDXY
1 5000 100
2 6000 200
Average 5500 150
Example Data Table

Example Code

<table>  <thead>    <tr>      <th>Sample ID</th><th>X</th><th>Y</th>    </tr>  </thead>  <tbody>    <tr>      <td>1</td><td>5000</td><td>100</td>    </tr>    <tr>
<td>2</td><td>6000</td><td>200</td>
</tr>  </tbody>  <tfoot>    <tr><td>Average</td><td>5500</td><td>150</td></tr>  </tfoot>  <caption>Example Data Table</caption></table>

Selectors

Selectors are a way to identify an element in the page. They do nothing in a pure HTML page, but are almost necessary if you want to use CSS or JavaScript along with the page.

Identifier (unique)

An id attribute must be unique - the only one on the page with that name. They are particularly useful for JavaScript, since the browser provides a way to easily find an element given an ID, but finding a class is slower and harder.

IDs are prefixed by a # (pound) when used in CSS.

The identifier is specified with the id attribute. For example: <img src="/logo.png" id="logo" /> assigns the image the #logo identifier. It should not have spaces or hyphens.

Class (categorical)

A class can be either unique or assigned to multiple elements on the page.

classes are prefixed by a . (period) when used in css.

The class is specified with the class attribute. Multiple classes can be specified in a single class attribute by using spaces. A class may have a hyphen. For example: <p class="comment new">Hello</p> is a paragraph that is both in the .comment class and .new class.

Invisible Tags

It is often extremely useful to organize portions of the page using invisible style-less tags, then define a style specific for the ID or class. In reality, any tag can be made to behave like any other tag by overriding enough styles, but that would be wasteful and difficult to develop.

<div> - Division Block

Div tags are blocks by default. This means that they take up all of the available width and push anything after it to below. They are easier to space between other blocks. Many times these are used to section areas of the page like headings, sidebars, footers, and pages.

<span> - Text

Span tags are inline by default. So, they only take up the space they need and can be used inline with text. For example, <strong>, <em>, <a>, and <img /> are all inline by default. These are mostly useful for highlighting sections of text.

CSS Introduction

Introduction

htmlTagName, #idname, .classname {   stylename: stylevalue;   color: black;   font-size: 12px;   background-color: #ddd;}

CSS stands for Cascading Style Sheet. In HTML, you use it to apply a certain look to specific elements in the page. CSS makes it easy to give every page on your website a unified appearance. The format is extremely straightforward, but to be effective you need to know how to specify which element you want styled, find current styling information in a webpage, and you must be aware of all of the styles that can be applied to an element. The general form of a style in a CSS file is like the example shown to the right.

Specifiers

Specifiers tell the browser which elements to apply the style to.

• tags like <body>, <p>, <div>, and <span> are specified with just the text
• an ID in html is declared in the element like <div id="rightSidebar">, and specified in CSS like #rightSidebar
• a class in html is declared in the element like <div class="gallery">, and specified in CSS like .gallery

Specifiers may be chained in special ways to select more elements or narrow in on an element

• Multiple specifiers can use the same style by seperating the specifiers with comments
• #sidebar, .gallery {...} applies the style within the brackets to both the sidebar ID and gallery class.
• You can drill down to an class by seperating specifiers with a space
• #sidebar h3 {...} applies the style within the brackets to only h3 elements within the sidebar element

Styling

Color

There are several ways to pick a color. The numerical methods all are in the order of "red, green, blue", with low numbers being darker and higher numbers being lighter.

CSS Color Examples
Name3 digit hex6 digit hexRGBRGB+Alpha Transparency
black #000 #000000 rgb(0,0,0) rgba(0,0,0,1.0)
white #FFF #FFFFFF rgb(255,255,255) rgba(255,255,255,1.0)
red #F00 #FF0000 rgb(255,0,0) rgba(255,0,0,1.0)
green #0F0 #00FF00 rgb(0,255,0) rgba(255,0,0,1.0)
blue #00F #0000FF rgb(0,0,255) rgba(0,0,0,1.0)
grey innaccurate #808080 rgb(129,129,129) rgba(129,129,129,1.0)
transparent N/P N/P N/P rgba(0,0,0,0)
N/P N/P N/P N/P rgba(0,0,0,0.5)

Styles List

Here are some sample styles applied to a div tag with the text "demo" inside of it.

Style NameDescriptionSample UsageSample Result
color The color of the font color: #090;
DEMO TEXT
font-size The size of the font, usually in px or em font-size: 14px;
DEMO TEXT
font-style Italicizes text font-style: italics;
DEMO TEXT
font-weight Controls the "boldness" of text font-weight: bold;
DEMO TEXT
text-decoration Underline, or overline, and strikethrough to text text-decoration:
underline;
DEMO TEXT
text-align The horizontal positioning of text text-align: center;
DEMO TEXT
vertical-align The vertical positioning of text vertical-align: middle;
DEMO TEXT
font-family Name of font. Use web-safe fonts! font-family: Serif;
DEMO TEXT
line-height Spaces text lines. 2em is 'double spaced' line-height: 2em;
DEMO TEXT
height
width
Controls the height/width of block elements width: 40px;
DEMO TEXT
background-color The background color of the box background-color: #fff;
DEMO TEXT
background Takes all background related styles
Can do color, image, image position, repeats
background: #fff
url() no-repeat
right 50%;
DEMO TEXT
border A line around the box border: 1px solid #090;
DEMO TEXT
DEMO TEXT
margin Adds spacing to the outside of the box margin: 5px;
DEMO TEXT
DEMO TEXT
float Pushes to side and surroundings wrap around it float: right;
DEMO TEXT
display inline: on same line as text like a span or img
block: use width and obey margins like div
inline-block: inline but can width and margin
none: not shown at all
display:inline;
DEMO TEXT
position static: the normal way of position
absolute: put at coordinates on screen
relative: like absolute, but zero'd at static
fixed: like absolute, but moves with scrolls
note: nonstatic needs top, left, right, or bottom
position: relative;
left: 10px;
DEMO TEXT
z-index Larger values are higher when overlapping z-index: 10;
-1px 0 0 #fff;
DEMO TEXT
Shadows can be inset (inside the box).
inset 0 0 2px #fff,
0 0 4px #000;
DEMO TEXT

Other Style Information

As a general rule, you can use a shorthand to differentiate the different directions of a style either in the order or top, right, bottom, left or in the order top+bottom and left+right. It follows a clockwise rule, and saves a lot of typing particularly on the margin and padding styles. For example:

Direction Notations
Seperated4 direction shorthand2 direction Shorthand
padding-top: 8px;padding-right: 5px;padding-bottom: 8px;padding-left: 5px;
padding: 8px 5px 8px 5px;
padding: 8px 5px;

The safe choices for fonts are really limited. With modern browsers, you can attach font files to pages. This process is made extremely easy with the Google Web Font API.

Development

As a general rule, you will want to have a local instance of the website you are developing for. If not, you can always test the css in-browser in chrome easily through menu > tools > developer tools. The magnifying glass in the bottom left will let you select an element visually on the screen. Then, the information on what styles are active and overridden is in the right column, and the tag's place in html is shown in the left. You can actually double click on just about anything in there and modify the contents of the page or the style information.

JavaScript and jQuery Introduction

Introduction

JavaScript is an actual programming language that is interpreted and run by your browser. It makes a webpage interactive and dynamic instead of just a rigid page that doesn't change once it's loaded. You can use it to send and recieve bits of information without having to load another page.  It allows you to drag and drop elements, or react to clicks and hovers. You can even use it to make an in-browser game.

It is syntactically similar to Java. It requires semi-colons at the end of each statement. However, it does not have rigid data types. Any variable can store data of any type - sort of like python. In fact, a variable can even store a function or actually contain nothing (undefined).

jQuery

Many of the ways you would routinely use JavaScript are made drastically easier by using the jQuery library. jQuery provides a simplified interface for finding elements in a webpage, easy methods for modifying styles and appending content, simple functions for doing making fluid transition animations, and a reliable way to send and recieve data like JSON to a server asyncronously.

Setting Up jQuery

the jQuery .js file simply needs to be included in the pages scripts. This can be done really easily by using Google's hosted libraries. One of the advanatages to using Google's hosted libraries is that the file may already be cached in the user's browser.

<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>

Using the JavaScript Console

The JavaScript console is extremely useful. In Chrome, it can be revealed by going to Options > Tools > Developer Tools > Console (the furthest tab to the right). This provides an interactive console. You can type a line of JavaScript, and you can read any errors or the output of any console.log() command in the JavaScript ran up until this point.

Searching for Elements

Elements in a webpage can be searched for extremely easily with jQuery. The the string used in the search is practically identical to the specifiers in CSS. ID's are specified with a # sign, classes are preceeded by a ., you can search for a specific drilldown by seperating specifiers by spaces, and seperate searches can be done simulteneously be using a comma.

Styles

Style information can be set and retrieved similar to the contents of an element. Select the element then use the css jQuery method to either retrieve or set the style by calling .css() with only the attribute or by calling it with both the attribute name and a value. It can also be called with a dictionary as an argument, with key value pairs corresponding to the css attribute names and values.

$("#comments .new").css("color", "#C00"); //adds to elements' style="" attribute Another way to change the style of an element would be to simply toggle a class on the element, then defining the CSS in a stylesheet. jQuery provides a lot of methods for this, like checking whether an element has a class (hasClass), adding a class (addClass), switching back and forth whether an element has a class (toggleClass), and removing a class (removeClass). Other style information can be easily retrieved and set in jQuery, like heights, widths, margins, positions on page, and scoll positions. Animation Styling can be easily animated with jQuery effects, which is possibly one of its most useful features. Some animations are predefined all having to do with hiding and revealing elements, like: hide(), .slideDown(), slideUp(), fadeIn, fadeOut $(".oops").hide()

Alternately, an animation can be completely customized with very little code by using the animate method. Many css values can be animated except colors, which requires jQuery UI. The first argument to animate is a dictionary of attributes and values for the styles, and the second argument is the duration of the animation in milliseconds.

$("#main").animate({ width: "50%" }, 1000 ); Events Events are what make JavaScript truly interactive. They allow your script to react to changes. Essentially, events are simply functions that are called whenever something happens. For example, if you want to make a webpage do something in response to a click, you simply say attach a function to an elements click event. function reactionToEvent() {$(this).text("CHANGED!"); //change calling elements text}$("#mybutton").click(reactionToEvent); Which is the same thing as: $("#mybutton").click(function() {   $(this).text("CHANGED!"); //change calling elements text}); There are all kinds of events available. One of the most common ones used in jQuery is to delay actions until the document is loaded by using:$(document).ready(handler)

Here are some of the other most common ones:
click, mousedown, mouseup - React to button presses
hover - Reacts to the mouse entering or leaving an element
keydownkeypress - Reacts to keyboard button presses like hotkeys.
change - Reacts to form elements being altered like inputs, select boxes, and radio buttons

There are many more events available than that, but they may require the use of the jQuery bind method.

Sending and Receiving JSON

JSON is an awesome tool for sending structured data to and from a server. You can retain the data types of any JavaScript variable, like a dictionary that has arrays that have all kinds of different data types. It turns the data types into a structured and linear string, which is a process called serializing. For example, a CSV is a sort of a way of serializing a two dimensional array.

var stuff = {   numbers: [0,1,3,6],   on: True,   comment: "Hello"};function successResponse(responseData) {   console.log(responseData); // dumps the data to browser's console}function failResponse() {   console.log("There was an error");}// send the stuff in JSON by POST to localhost and run the above function when done$.ajax({ type: "POST", url: 'localhost', dataType: 'json', data: stuff, success: successResponse }).fail(failResponse); PD Feedback Control Introduction Uses A PD controller can be used in a real-time on a robot where a goal value can be both measured and controlled. A PD control is robust, which means that it can overcome unexpected behavior. For example, a PD controller could be used in the cruise control on a car. The driver decides the goal speed and the controller in the car could see how fast the car is going, since cars have a speedometer. Under ideal conditions, all it would take to maintain speed is to keep the engine throttled at a predetermined constant amount. However, many unforseable factors can change how much gas is needed to maintain speed. For example, the quality of the gas, engine temperature, road incline, and wind speed. A controller needs to be able to overcome these unpredictable or difficult to measure sources of error to maintain a given speed and accelerate or decellerate as needed. Premise PD stands for proportion and derivative. • Multiplying a constant (kp) to the "error" - or the difference between the desired and current values - will pull the output towards the desired value. A larger proportion constant means faster responses. • Multiplying another constant (kd) to the rate of change in the error essentially says "slow down before you get there". It keeps the system from vibrating by anticipating the error. More anticipation means less vibration. Analogy Cars have shock absorbers and springs on each of their wheels. The springs try to keep the car a certain distance off the ground. This is like the proportion in a PD controller, but usually this "error" distance is zero. The shock absorber on a car is a damper, which helps the car to stop vibrating from the springs - just like the derivative portion of a PD controller. The similarity between the suspension system and a PD controller is due to the spring and damper pairing. Obviously, it is not exactly a control system. Rather, if you visualize the position graphs in terms of current position and goal position, you begin to see how a PD controller will behave. Just like this suspension system controls the hight of a car based on the position of its tire, you can robustly control just about anything your robot has the ability to both affect and sense. It does not have to be a position. For example, you could control the temperature of an oven as long as you have control of the heating element and have a temperature sensor inside the oven. An Example Problem So, lets say you have a motor and an encoder that allows you to read the position of the motor. You want the motor to go to a goal position of your choosing. This motor is attached to a vertical rack and pinion so that the graph is easy to visualize. Bad Solution You could say "if you're not there, go towards the goal", like this Arduino code: if ( position < goal ) { // too low goUp(); // set direction analogWrite(motor, 255); // go full speed}else if ( position == goal ) { // at goal analogWrite(motor, 0); // stop }else if ( position > goal ) { // too high goDown(); // set direction analogWrite(motor, 255); // go full speed } The problem here is that many times the system will have sufficient momentum to keep going even though there is no more current and no force being applied by the motor. Unless there is sufficient friction, you will overshoot the goal. If this happens once, it'll probably happen on the next pass too - resulting in vibration. This is obviously undesirable since the system never rests at the goal position, wastes energy, and will wear down unecessarily. Good Solution Now lets simply change the code on the Arduino microcontroller to use a PD control. // the PD controller requires speed be calculatedint output = Kp*(goal-position) - Kd*speedif ( output >= 0 ) { // positive goUp(); // set direction analogWrite(motor, output); // go partial speed}else { // negative goDown(); // set direction analogWrite(motor, -output); // go partial speed } Note that this new PD control requires the speed, not just the position. This is not usually a problem, since a microcontroller is usually pretty good at keeping time. You can simply keep track of the change in position divided by the change in time. This requires a little more code on the Arduino. unsigned long now = micros(); // store the current time in "now"// change in position over change in timespeed = ( position - lastPosition ) / ( now - lastTime )// this measurement is now the previous onelastPosition = position;lastTime = now; Depending on the values that you pick for the variables Kp and Kd, you could get two different kinds of behaviors: damped vibration (left), or a critically/over damped system (right). Choosing Values Picking the right Kp and Kd values is important. To some extent, you can just do it by trial and error. Desired ResultChange Get There Fast (low rise time) Smaller Kp Less Overshoot Smaller Kp, Larger Kd Less Vibration Larger Kd It is no exagguration to say that there is a science to picking the right parameters, though. They can actually be precisely chosen by using math. Essentially, you need to be able to describe what you are controlling with an equation to make a transfer function, then find the characteristic equation. It's actually a lot easier than it sounds. Using Node.js as a web server Introduction Node.js is JavaScript that can be run outside of a browser. It is often used to make a fast server for dynamic content. Probably one of the biggest advantages to Node.js, aside from being one of the fastest and easiest to learn server environments, is that JavaScript is the lanugage used on browsers, allowing you to program both the server and client in the same language. Example First, download and install node.js Then, start the example by usign the command: nodejs server.js This example starts by sending a static HTML form when you visit http://localhost:8080/. It looks like the image below: Clicking the submit button on the form sends a get request to http://localhost:8080/submit. It looks like the image below. The interesting part of this script is the (url_parts.pathname == '/submit') condition. This is where the dynamic page generation happens. It starts by just regurgitating the information it was sent in the form. Note that the variable names of the url_parts.query.varname match up to the "name" attribute in each of the form elements. One of the most powerful features of node.js is that the program remains running between requests, unlike PHP. As a result, we can store variables which can retain their values as long as the process stays running. Storing any really important information this way is a bad idea, since a crash or shutdown would cause the data to disappear. A database can be used, such as MySQL. However, probably the most popular database for node.js servers is MongoDB, which uses JSON encoded data. This form would also work by POST, if the form method were changed from GET to POST. var http = require('http'); // these lines are somewhat similar to #include in C++ var util = require('util'); // except that the left hand side is an object/variable var url = require('url'); var fs = require('fs'); // provide a "database" messages = [] var server = http.createServer(function (req,res){ // parse the URL var url_parts = url.parse(req.url,true); // functions to serve static files function sendHTML(filepath) { // read the file asyncronously fs.readFile(filepath,function(error,contents){ // once the file is loaded, this function runs console.log('Serving the html ' + filepath); res.end(contents); // end the request and send the file }); } function sendCSS(filepath) { // once the file is loaded, this function runs fs.readFile(filepath,function(error,contents){ console.log('Serving the css ' + filepath); res.end(contents); // end the request and send the file }); } // serve the index page from a static file if( url_parts.pathname == '/' ) { sendHTML('./form.html'); } // serve the CSS page from a static file else if ( url_parts.pathname == '/style.css') { sendCSS('./style.css') } // generate a dynamic page else if ( url_parts.pathname == '/submit' ) { var html = '<html><body>'; // begin the minimal html structure html += "<h2>Query received</h2>"; html += "Name: " + url_parts.query.name; html += '<br />'; html += "Email: " + url_parts.query.email; html += '<br />'; html += "Message: " + url_parts.query.message; html += '<br />'; html += '<h2>Previous Messages</h2>'; messages.push(url_parts.query.message) // loop through the old messages for(m in messages) { html += messages[m]; html += '<br />'; } html += '</body></html>'; // end the minimal html structure res.end(html); // end the request and send the response HTML } // if the url was not recognized, 404 else { res.writeHead(404) // put a header for not found // print the page and end the request res.end("<h1>404 - Path not recognized</h1>"); } }); server.listen(8080); util.log('Server listenning at localhost:8080'); Attachments: Python GUIs Preface Unless your robot is completely autonomous, you'll probably want a nice, centralized, and graphical way to control it. Really, you can use anything that can output to serial. Python is a really easy way to accomplish this with minimal programming thanks to its easy syntax and some well built libraries like pySerial, Tkinter, and Tornado. Python provides a easy-to-use library called Tkinter that allows the user to make GUIs. This is a good way to get a nice windowed GUI on nearly most platforms (Windows, Mac, Linux). It requires minimal setup, and is relatively simple to use. Another option for a Graphical User Interface is Tornado, which is a web server. With a web server, you can control your system from anywhere with an internet connection with anything with a web browser. Basics of a Tkinter GUI Introduction It is often necessary to being to communicate with a robot while it is in use. This can be done simply through a remote control or more complexly through a GUI. The GUI can allow the robot to both send an receive information while a remote control will only be able to send to the robot. A simple way to make a GUI is through Python Tkinter. Using Tkinter along with Serial, the code will allow easy communication between the robot. This tutorial will show how to use various parts of Tkinter and show how to make a GUI look good. Importing Library At the start of the code, it is necessary to import the necessary libraries: from Tkinter import *  Importing the library in this fashion means that when the library is used, it does not have to be called every time. For communication between a robot, it will also be necessary to import the Serial library. To learn more about that, see Serial Commands. Making a GUI The first thing that must be done is to make the window that the GUI will be in. This is done with the following code: root = Tk() #Makes the window root.wm_title("Window Title") #Makes the title that will appear in the top left root.config(background = "#FFFFFF") #sets background color to white#put widgets hereroot.mainloop() #start monitoring and updating the GUI. Nothing below here runs.  This gives a very basic window with a white background. When making a Python GUI, there are several different widgets that can be used. Here, the following widgets will be discussed: • Frame • Label • Entry • Button • Canvas • Text Frame Frames are useful for the organization of a GUI. Frames get built into the grid of the window and then in turn each have a grid of their own. This means that nesting frames may be necessary if the GUI is going to look nice. To add a frame, the following code is needed: leftFrame = Frame(root, width=200, height = 600) leftFrame.grid(row=0, column=0, padx=10, pady=2)  The first line means that leftFrame will rest in root, which is the name that the window was given. The height and width are specified, but the frames re-size to what is put inside. The second line places the frame in the first grid spot open in root (0,0). Label A label allows either text or a picture to be placed. The text inside the label can be updated later if necessary. To add a label, the following code is needed: firstLabel = Label(leftFrame, text="This is my first label") firstLabel.grid(row=0, column=0, padx=10, pady=2)  This rests firstLabel in left frame with the following text in the first spot of leftFrame. To get a picture in the label, the following code is used: imageEx = PhotoImage(file = 'image.gif') Label(leftFrame, image=imageEx).grid(row=0, column=0, padx=10, pady=2)  The image should be in the same folder that the Python file is in. Using PhotoImage, the image file should be a GIF or PGM. Entry The Entry widget is an input widget. It allows the user to type something that can then be read into the program. To use this widget, the following code is helpful: userInput = Entry(leftFrame, width = 10) #the width refers to the number of characters userInput.grid(row=0, column=0, padx=10, pady=2) #get the text inside of userInput userInput.get()  It may be necessary to get the inside of the entry when a button is pushed or when the user strikes enter. Button A button causes a specified action to occur. To use a button, the following is needed: newButton = Button(leftFrame, text="Okay", command=btnClicked) newButton.grid(row=0, column=0, padx=10, pady=2)  The command specified in the button is a function that will be called. The function holds the code that should fire when the button is pushed. This function should be above when the button is made. Canvas A canvas allows for various shapes and designs to be drawn onto it. These shapes will remain if more are added unless the shape's pixels are completely overwritten. To add a canvas, the following code is used: newCanvas = Canvas(leftFrame, width=100, height=100, bg='white') newCanvas.grid(row=0, column=0, padx=10, pady=2)  This gets the canvas. To draw on the canvas there are a large number of functions available, such as create_arc and create_line. Text A Text widget can either be written in or can be written to. To use it, the following is needed: newText = Text(leftFrame, width=50, height=8, takefocus=0) newText.grid(row=0, column=0, padx=10, pady=2) #write to widget newText.insert(0.0, "Text to insert") #0.0 is beginning of widget  The Text widget is good for creating logs since the data will remain and the user can look back at it. GUI Example It is often useful to map out what the GUI is going to look like before starting on it so that all the frames can be nested appropriately. A sketch should be made for the GUI so that it can be visualized, such as the following: In the above example, only three frames would be necessary: a frame for the left side, a frame for the right side, and a frame surrounding the color buttons. Using this along with the code that was given previously, the following code can be made: from Tkinter import * root = Tk() #Makes the window root.wm_title("Window Title") #Makes the title that will appear in the top left root.config(background = "#FFFFFF") def redCircle(): circleCanvas.create_oval(20, 20, 80, 80, width=0, fill='red') colorLog.insert(0.0, "Red\n") def yelCircle(): circleCanvas.create_oval(20, 20, 80, 80, width=0, fill='yellow') colorLog.insert(0.0, "Yellow\n") def grnCircle(): circleCanvas.create_oval(20, 20, 80, 80, width=0, fill='green') colorLog.insert(0.0, "Green\n") #Left Frame and its contents leftFrame = Frame(root, width=200, height = 600) leftFrame.grid(row=0, column=0, padx=10, pady=2) Label(leftFrame, text="Instructions:").grid(row=0, column=0, padx=10, pady=2) Instruct = Label(leftFrame, text="1\n2\n2\n3\n4\n5\n6\n7\n8\n9\n") Instruct.grid(row=1, column=0, padx=10, pady=2) try: imageEx = PhotoImage(file = 'image.gif') Label(leftFrame, image=imageEx).grid(row=2, column=0, padx=10, pady=2) except: print("Image not found") #Right Frame and its contents rightFrame = Frame(root, width=200, height = 600) rightFrame.grid(row=0, column=1, padx=10, pady=2) circleCanvas = Canvas(rightFrame, width=100, height=100, bg='white') circleCanvas.grid(row=0, column=0, padx=10, pady=2) btnFrame = Frame(rightFrame, width=200, height = 200) btnFrame.grid(row=1, column=0, padx=10, pady=2) colorLog = Text(rightFrame, width = 30, height = 10, takefocus=0) colorLog.grid(row=2, column=0, padx=10, pady=2) redBtn = Button(btnFrame, text="Red", command=redCircle) redBtn.grid(row=0, column=0, padx=10, pady=2) yellowBtn = Button(btnFrame, text="Yellow", command=yelCircle) yellowBtn.grid(row=0, column=1, padx=10, pady=2) greenBtn = Button(btnFrame, text="Green", command=grnCircle) greenBtn.grid(row=0, column=2, padx=10, pady=2) root.mainloop() #start monitoring and updating the GUI  This code results in the following GUI: This GUI completes all the functions it is intended to do, but does not do so in a very aesthetic fashion. Making the GUI Attractive Introduction It is one thing to make a GUI and another to make a GUI that people will want to use. Despite the fact that the appearance of a GUI does not really affect how the program runs, it is always prudent to set up GUIs in a way that they could be presented professionally. Although, this is really only important if the GUI runs properly. Making it function accordingly is always more important than its appearance. Note: This will focus on improving the GUI example from the previous tutorial. Making Frames the Same Height When GUIs with multiple frames are built, it can be seen that each frame is its own unique size based on what is in each frame. Usually, this is a nuisance. Fortunately, there is an easy fix: Sticky. This gets added when you put it in the grid: leftFrame.grid(row=0, column=0, padx=10, pady=2, sticky=N+S) The options for Sticky are: N, E, S, W. Justification of Text in Labels If there is only one line of text in the label, the text can be justified by using Anchor. However, sometimes it is necessary to have more than one line of text, such as the instructions label. In this case, it is necessary to use Wraplength to get the text wrapped. Unfortunately, this wants the wrap length in pixels rather than characters, so that can be a bit of a guessing game to get it right. If there is more than one line of text, it should also include Justify. The code below shows an example of justification of multiple text to the left: Instruct = Label(leftFrame, width=22, height=15, text=instructions, takefocus=0, wraplength=170, anchor=W, justify=LEFT) The options for Anchor are: N, NE, E, SE, S, SW, W, NW, CENTER. The options for Justification are: LEFT, RIGHT, CENTER. Fonts The main thing with fonts, is not to pick really obnoxious fonts that people are not going to want to look at. Simple fonts are better for the main GUI and if a stylized font is desired for only select portions, that is fine as long as the stylized font is not too crazy. Fonts are added by using the following code: Instruct = Label(leftframe, width=30, height=9, text=instructions, takefocus=0, wraplength=275, font=("MS Serif", 12), anchor=W, justify=LEFT, background=framebg) Background Colors The initial background Python uses is white, which is a bit boring. To chose unique colors, it may be necessary to look up their RGB color codes. However, caution should be given when choosing colors. They should not be obnoxiously bright so that they attract away from the attention of the GUI itself. The colors should be neutral and minimally invasive. This doesn't mean to only use beige or boring colors, but to choose gentler colors that people will not mind staring at. The font color is added when the declaration was made, or can change later if needed: leftFrame = Frame(root, width=200, height = 600, bg="#C8F9C4") However, changing a frame does not change the color of the labels, so the background specification can be added to all of those as well. Borders Adding borders can be a nice touch to the various components in the GUI. To do this, the code should refer to the hightlight thickness, which determines the width of the border in pixels, and the highlight background, which refers to the backgrounds color. An example of this is below: leftFrame = Frame(root, width=200, height = 600, bg="#C8F9C4", highlightthickness=2, highlightbackground="#111") Visual Arrangement The arrangement of the GUI should be uncluttered and easy to read. Like options should be catergorized together, but seperated from other components. A lot of this is a matter of taste on who the end user is, so keep that in mind when designing GUIs. GUI Example Looking at the same GUI from the previous tutorial, here is the code to clean it up: from Tkinter import * root = Tk() #Makes the window root.wm_title("Window Title") #Makes the title that will appear in the top left root.config(bg = "#828481") def redCircle(): circleCanvas.create_oval(20, 20, 80, 80, width=0, fill='red') colorLog.insert(0.0, "Red\n") def yelCircle(): circleCanvas.create_oval(20, 20, 80, 80, width=0, fill='yellow') colorLog.insert(0.0, "Yellow\n") def grnCircle(): circleCanvas.create_oval(20, 20, 80, 80, width=0, fill='green') colorLog.insert(0.0, "Green\n") #Left Frame and its contents leftFrame = Frame(root, width=200, height = 600, bg="#C8F9C4", highlightthickness=2, highlightbackground="#111") leftFrame.grid(row=0, column=0, padx=10, pady=2, sticky=N+S) Inst = Label(leftFrame, text="Instructions:", anchor=W, bg="#C8F9C4") Inst.grid(row=0, column=0, padx=10, pady=2, sticky=W) instructions = "When one of the buttons on the is clicked, a circle\ of the selected color appears in the canvas above. Red will result in a red circle. The color that is\ selected will also appear in the output box below. This will track the various colors that\ have been chosen in the past." Instruct = Label(leftFrame, width=22, height=10, text=instructions, takefocus=0, wraplength=170, anchor=W, justify=LEFT, bg="#C8F9C4") Instruct.grid(row=1, column=0, padx=10, pady=2) imageEx = PhotoImage(file = 'image.gif') Label(leftFrame, image=imageEx).grid(row=2, column=0, padx=10, pady=2) #Right Frame and its contents rightFrame = Frame(root, width=200, height = 600, bg="#C8F9C4", highlightthickness=2, highlightbackground="#111") rightFrame.grid(row=0, column=1, padx=10, pady=2, sticky=N+S) circleCanvas = Canvas(rightFrame, width=100, height=100, bg='white', highlightthickness=1, highlightbackground="#333") circleCanvas.grid(row=0, column=0, padx=10, pady=2) btnFrame = Frame(rightFrame, width=200, height = 200, bg="#C8F9C4") btnFrame.grid(row=1, column=0, padx=10, pady=2) colorLog = Text(rightFrame, width = 30, height = 10, takefocus=0, highlightthickness=1, highlightbackground="#333") colorLog.grid(row=2, column=0, padx=10, pady=2) redBtn = Button(btnFrame, text="Red", command=redCircle, bg="#EC6E6E") redBtn.grid(row=0, column=0, padx=10, pady=2) yellowBtn = Button(btnFrame, text="Yellow", command=yelCircle, bg="#ECE86E") yellowBtn.grid(row=0, column=1, padx=10, pady=2) greenBtn = Button(btnFrame, text="Green", command=grnCircle, bg="#6EEC77") greenBtn.grid(row=0, column=2, padx=10, pady=2) mainloop() Here is the result: Python Web UI with Tornado Introduction So, you want a GUI for your robot. Sure, you could make a nice GUI in Python with Tkinter, but there are some really good reasons to try it as a website instead: • A web GUI can be accessed from almost any location • A well-designed web GUI can be used on almost any device like a tablet or a phone • HTML, CSS, and Javascript are well documented, powerful, and very flexible • HTML can be easily made to look very nice There are some drawbacks to implementing your GUI as a website though: • It is only able to start communication one-way (browser to server, server responds) • Great for buttons and other input • Requres continuous polling or a commet to get data to be pushed to the browser • It adds another "layer" of complexity to your code • Several different languages (C++ on Arduino, Python Server, and HTML+CSS+Javascript in browser) • The server has to relay information from the browser to the robot Installing Python Tornado I used the Tornado web server for my projects. It is better than just using CGI, since the environment is always loaded while the server is running instead of loading it every time a request is made. CGI would be problematic then, since serial.begin would be run every time a request was made, which simply wouldn't work since the Arduino would also restart all the time. On Ubuntu, the installation is as easy as: sudo apt-get install python-tornado python-serial Using Tornado with the Serial Library So one of the challenges with this is that reading serial input in python is usually blocking, so the webserver becomes unresponsive to browsers' requests while waiting for serial input. #! /usr/bin/python2.7 import os import json import tornado.ioloop import tornado.web from serial import * tornadoPort = 8888 cwd = os.getcwd() # used by static file server # Make a Serial object serialPort = '/dev/ttyACM0' serialBaud = 9600 ser = Serial( serialPort, serialBaud, timeout=0, writeTimeout=0 ) # gets serial input in a non-blocking way serialPending = '' def checkSerial(): try: s = ser.read( ser.inWaiting() ) except: print("Error reading from %s " % serialPort ) return if len(s): serialPending += s paseSerial() #called whenever there is new input to check serialHistory = '' mostRecentLine = '' def parseSerial(): split = serialPending.split("\r\n") if len( split ) > 1: for line in split[0:-1]: print( line ) #do some stuff with the line, if necessary #example: mostRecentLine = line # in this example, status will show the most recent line serialHistory += line pending = split[-1] # send the index file class IndexHandler(tornado.web.RequestHandler): def get(self, url = '/'): self.render('index.html') def post(self, url ='/'): self.render('index.html') # handle commands sent from the web browser class CommandHandler(tornado.web.RequestHandler): #both GET and POST requests have the same responses def get(self, url = '/'): print "get" self.handleRequest() def post(self, url = '/'): print 'post' self.handleRequest() # handle both GET and POST requests with the same function def handleRequest( self ): # is op to decide what kind of command is being sent op = self.get_argument('op',None) #received a "checkup" operation command from the browser: if op == "checkup": #make a dictionary status = {"server": True, "mostRecentSerial": mostRecentLine } #turn it to JSON and send it to the browser self.write( json.dumps(status) ) #operation was not one of the ones that we know how to handle else: print op print self.request raise tornado.web.HTTPError(404, "Missing argument 'op' or not recognized") # adds event handlers for commands and file requests application = tornado.web.Application([ #all commands are sent to http://*:port/com #each command is differentiated by the "op" (operation) JSON parameter (r"/(com.*)", CommandHandler ), (r"/", IndexHandler), (r"/(index\.html)", tornado.web.StaticFileHandler,{"path": cwd}), (r"/(.*\.png)", tornado.web.StaticFileHandler,{"path": cwd }), (r"/(.*\.jpg)", tornado.web.StaticFileHandler,{"path": cwd }), (r"/(.*\.js)", tornado.web.StaticFileHandler,{"path": cwd }), (r"/(.*\.css)", tornado.web.StaticFileHandler,{"path": cwd }), ]) if __name__ == "__main__": #tell tornado to run checkSerial every 10ms serial_loop = tornado.ioloop.PeriodicCallback(checkSerial, 10) serial_loop.start() #start tornado application.listen(tornadoPort) print("Starting server on port number %i..." % tornadoPort ) print("Open at http://127.0.0.1:%i/index.html" % tornadoPort ) tornado.ioloop.IOLoop.instance().start() Setting up the Browser To make it easy to send requests to the server, it's really a good idea to use jquery, and the easiest way to use jquery is to use the Google API for it. To add jquery to the webpage, just add this script: <script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js"></script>  So to start, we'll just have a simple webpage that has a div. When the div is clicked, jquery will ask the status of the tornado webserver. <!DOCTYPE html> <html> <head> <title>Python Tornado Test Page</title> <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script> <script> function serverResponded( data ) { /* log the event data, so you can see what's going on. Shows up in the console on your browser. (Chrome: Tools > Developer Tools > Console) */ console.log( data ); // check the server status, and report it on the screen if ( data.server === true ) {$('#status .value').html("OK");
}
else {
$('#status .value').html("NOT OK"); } // add the last serial to the div on the screen$('#serial .value').html( data.mostRecentSerial );
}

$(document).ready( function() { /* handle the click event on the clickme */$('#clickme').click( function() {
params = { op: "checkup" };
$.getJSON( 'http://localhost:8888/com' , params, serverResponded ); }); }); </script> </head> <body> <div id="clickme" style="cursor: pointer;">CLICK ME</div> <div id="status"> Server Status: <span class="value">?</span> </div> <div id="serial"> Last Serial Input: <span class="value"></span> </div> </body> 3D SVG Graph Introduction An SVG is a type of graphic that is defined by shapes and math instead of discrete pixels. So, it is scales nicely, but can't make photo-realistic images. An (currently) SVG is two dimensional. That does not mean, though, that we cannot represent 3D information in this 2D space. After all, it is shown in 2D anyway. To accomplish this, we will build our own 3D rotation matrices, and a 3D to 2D projection matrix. The 3D points can be multiplied by both of these matrices to make it appear 3D, albeit somewhat flat due to the orthographic projection. Interactive Graph Demo This SVG grapher was made so that a user easily visualize and control the end manipulator of a robotic arm in 3D through a web browser. It may be viewed on this page on the NIU College of Engineering and Engeering Technology website, but the arm is usually left off for safety. Hold left click and drag to move point. Hold middle click and drag to rotate. Usage Although the implementation starts to get somewhat complicated, the usage is actually somewhat straightforward. Get the attached javascript file, and make an html file that contains this: <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script> <script src="3dgraph.js"></script> <svg xmlns="http://www.w3.org/2000/svg" version="1.1" height="320" width="352" id="3d-graph" style="height: 320px; width:342px; margin: 0 auto; padding: 5px;" > <!-- neg axis --> <line x1="100" y1="250" x2="400" y2="250" id="neg-axis-x" style="stroke:rgba(250,200,200,0.5);stroke-width:2"/> <line x1="100" y1="250" x2="100" y2="0" id="neg-axis-y" style="stroke:rgba(200,250,200,0.5);stroke-width:2"/> <line x1="100" y1="250" x2="0" y2="400" id="neg-axis-z" style="stroke:rgba(200,200,250,0.5);stroke-width:2"/> <!-- axis --> <line x1="100" y1="250" x2="400" y2="250" id="axis-x" style="stroke:rgb(200,0,0);stroke-width:2"/> <line x1="100" y1="250" x2="100" y2="0" id="axis-y" style="stroke:rgb(0,200,0);stroke-width:2"/> <line x1="100" y1="250" x2="0" y2="400" id="axis-z" style="stroke:rgb(0,0,200);stroke-width:2"/> </svg>  Interfacing The coordinates of the point above are stored in the variables tx, ty, and tz. If you just wish to read it, just read the variables. If you modify them, you have to update the display with mainDot.changePoint() A point is simply a vector. A dot is the point plus the graphical representation. A line is two points and a graphical connection between them. How it Works This implementation uses the jQuery library, which is much less useful than usual since jQuery can only create HTML DOM objects and not SVG DOM objects as required in this usage. It is still useful for it's event bindings and some search features. There is a point class with an x, y, and z. Points are used to in the graphical classes Dot and Line, where line has two points for a start and an end. Points are multiplied by rotation and projection matrices to turn their 3 dimensions into 2 dimensions. The rotation matrix angles are modified by mouse movement during a click event. When the rotation matrix is changed, the points must be multiplied with the new matrix and the result must be updated on the SVG. In this specific usage, there were 7 points used for the axes. A zero point and points at the maximum and minimum (positive and negative) for each direction. There is a dot at the point you want to visualize in the 3D space, as well as 3 guide lines to help with perspective. The guide lines are entirely necessary. It would also be possible to plot a curved line by using many Line classes or even making your own class that uses the SVG path tag to generate a smooth curve. Another possible feature might be to put a Dot class at a point on the lone closest to the mouse and showing the x,y, and z coordinates. Attachments: Tkinter with Serial Introduction To use Python as a graphical interface for an Arduino powered robot, programmatically read the USB with the pySerial library. However, waiting for input from pySerial's Serial object is blocking, which means that it will prevent your GUI from being responsive. The process cannot update buttons or react to input because it is busy waiting for the serial to say something. The first key is to use the root.after(milliseconds) method to run a non-blocking version of read in the tkinter main loop. Keep in mind that when TkInter gets to the root.mainloop() method, it is running its own while loop. It needs the things in there to run every now and then in order to make the interface respond to interactions. If you are running your own infinite loop anywhere in the code, the GUI will freeze up. Alternatively, you could write your own infinite loop, and call root.update() yourself occasionally. Both methods achieve basically the same goal of updating the GUI. However, the real issue is making sure that reading from serial is non-blocking. Normally, the Serial.read() and Serial.readline() will hold up the whole program until it has enough information to give. For example, a Serial.readline() won't print anything until there is a whole line to return, which in some cases might be never! Even using the after() and update() methods will still not allow the UI to be updated in this case, since the function never ends. This problem can be avoided with the timeout=0 option when enitializing the Serial object, which will cause it to return nothing unless something is already waiting in the Serial object's buffer. Code from serial import *from Tkinter import *serialPort = "/dev/ttyACM0"baudRate = 9600ser = Serial(serialPort , baudRate, timeout=0, writeTimeout=0) #ensure non-blocking#make a TkInter Windowroot = Tk()root.wm_title("Reading Serial")# make a scrollbarscrollbar = Scrollbar(root)scrollbar.pack(side=RIGHT, fill=Y)# make a text box to put the serial outputlog = Text ( root, width=30, height=30, takefocus=0)log.pack()# attach text box to scrollbarlog.config(yscrollcommand=scrollbar.set)scrollbar.config(command=log.yview)#make our own buffer#useful for parsing commands#Serial.readline seems unreliable at times tooserBuffer = ""def readSerial(): while True: c = ser.read() # attempt to read a character from Serial #was anything read? if len(c) == 0: break # get the buffer from outside of this function global serBuffer # check if character is a delimeter if c == '\r': c = '' # don't want returns. chuck it if c == '\n': serBuffer += "\n" # add the newline to the buffer #add the line to the TOP of the log log.insert('0.0', serBuffer) serBuffer = "" # empty the buffer else: serBuffer += c # add to the buffer root.after(10, readSerial) # check serial again soon# after initializing serial, an arduino may need a bit of time to resetroot.after(100, readSerial)root.mainloop() Projects Preface All this knowledge is great, but you really learn best by practicing what you learn. If you'd like some ideas for some fun projects to hone your skills on, we've been looking for the same thing. These are some projects that we have liked doing. A lot of them are going to have to do with Arduino - it's a great platform, we like using it, and you should too. Arduino Sketcher Introduction I had gotten a joystick a while ago and wanted to do something different and interesting with it. After coming up with and discarding a bunch of other ideas, I came up with the Arduino Sketcher. The ideas was to make something similar to an Etch-a-Sketch but uses the joystick instead of two dials. The computer would serve as the sketching pad while to Arduino relayed all the commands sent by the user. This project uses both Arduino and Python and turned out to be fairly simple to implement. Schematic Below is the schematic of the Arduino Sketcher. The sketcher allows the user to click on various parts of the canvas to determine where the lines start out. This allows for disconnected lines. It uses the joystick to determine where to draw the line and how quickly. The more the user shifts the joystick, the faster it draws lines. When the user holds the joystick down, the button triggers and a circle will be drawn on the canvas. The longer the button is held down, the larger the circle is. The buttons next to the joystick allow the user to select various colors indicated by the wire. There are buttons available that are colored and can be used to indicate color. Code Arduino Code Below is the code on the Arduino side. The Arduino is mostly used to translate the controller and send commands to the Python side. /**************************** Controller for Sketcher Jennifer Case 13/06/2013 ****************************/ //Declare pins int redPin = 7; int yelPin = 6; int grnPin = 5; int bluPin = 4; int blkPin = 3; int verPin = A0; int horPin = A1; int circlePin = 8; int lastColor = 4; long previousMillis = 0; long interval = 200; float numClicks = 0; void setup() { Serial.begin(38400); pinMode(redPin, INPUT); pinMode(yelPin, INPUT); pinMode(grnPin, INPUT); pinMode(bluPin, INPUT); pinMode(blkPin, INPUT); pinMode(circlePin, INPUT); digitalWrite(circlePin, HIGH); } void loop() { //read values from color buttons int redBtn = digitalRead(redPin); int yelBtn = digitalRead(yelPin); int grnBtn = digitalRead(grnPin); int bluBtn = digitalRead(bluPin); int blkBtn = digitalRead(blkPin); //read and normalize values from the potentiameters float verPos = (analogRead(verPin)-504.0)/504.0; float horPos = (496.0-analogRead(horPin))/496.0; //read value of button boolean circleBtn = digitalRead(circlePin); //if either normalized value from the joystick is //essentially zero, make it equal zero if (verPos < 0.01 && verPos > -0.01) {verPos = 0;} if (horPos < 0.01 && horPos > -0.01) {horPos = 0;} unsigned long currentMillis = millis(); char charBuf[5]; //if enough time has passed and either potentiameter is not zero, //print out commands for both axes if(currentMillis - previousMillis > interval && (verPos != 0 || horPos != 0)) { Serial.print("X,"); dtostrf(verPos, 4, 2, charBuf); //turn float to string Serial.println(charBuf); Serial.print("Y,"); dtostrf(horPos, 4, 2, charBuf); //turn float to string Serial.println(charBuf); previousMillis = currentMillis; //reset the interval } //determine color and print it to sketcher if it was not the last color if (redBtn && lastColor != 0) { Serial.println("C,R"); //print command lastColor = 0; } else if (yelBtn && lastColor != 1) { Serial.println("C,Y"); //print command lastColor = 1; } else if (grnBtn && lastColor != 2) { Serial.println("C,G"); //print command lastColor = 2; } else if (bluBtn && lastColor != 3) { Serial.println("C,B"); //print command lastColor = 3; } else if (blkBtn && lastColor != 4) { Serial.println("C,K"); //print command lastColor = 4; } //while button on joystick is clicked, while (!circleBtn) { numClicks++; //increase counter circleBtn = digitalRead(circlePin); //read the button again } //if numClicks is more than zero, if (numClicks > 0) { Serial.print("O,"); //start printing command numClicks = numClicks/20000.0; //normalize the numClicks dtostrf(numClicks, 4, 2, charBuf); //int to string Serial.println(charBuf); //print the rest of the command numClicks = 0; //reset numClicks } } Python Code Below is the Python code. It just translates the commands from the Arduino side and draws the appropriate lines on the canvas. It should be noted that this was coded for Python 3. #! /usr/bin/python from serial import * from tkinter import * import time #Serial ser = Serial("COM9",38400,timeout=0,writeTimeout=0) time.sleep(1) #initialize positions xPos = 500 yPos = 300 #function for making a circle def drawcircle(canv,x,y,rad,color): canv.create_oval(x-rad,y-rad,x+rad,y+rad,width=0,fill=color) #function for mouse click def goToClick(event): global xPos global yPos xPos = event.x yPos = event.y #Main window root = Tk() #Tk is a function that makes a class root.wm_title("Canvas Sketch") root.config(bg="#8D8A8A", bd="0") #make the sketcher canvas sketcher = Canvas(root, width=1000, height=600, bg='white') sketcher.grid(row=0, column=0) sketcher.bind('<Button-1>', goToClick) #log = Text(root, width=50, height=8, takefocus=0) #log.grid(row=1, column=0, padx=2, pady=2) #initializations color = 'black' verPos = 0 horPos = 0 def runLoop(event=0): ln = ser.readline() #get command lineStr = ln.decode(encoding='UTF-8') #log.insert('0.0',lineStr) #print(lineStr) #initializations Xline = 0 Yline = 0 circline = 0 newLine = 0 #other neccessary variables global verPos global horPos global xPos global yPos global color #determine selected color if "C" in lineStr: for line in lineStr.split(','): if "R" in line: color = 'red' if "Y" in line: color = 'yellow' if "G" in line: color = 'green' if "B" in line: color = 'blue' if "K" in line: color = 'black' #get X value elif "X" in lineStr: if len(lineStr) > 6: #make sure length is appropriate for line in lineStr.split(','): if Xline == 1: #take value from lineStr verPos = float(line.strip("\n \r"))*-1 #fix direction #print(verPos) Xline = 0 elif Xline == 0: Xline = 1 #get Y value elif "Y" in lineStr: for line in lineStr.split(','): if Yline == 1: #take value from lineStr horPos = float(line.strip("\n \r")) #print(horPos) Yline = 0 newLine = 1 #indicates that a line is ready to be drawn elif Yline == 0: Yline = 1 #draw circle elif "O" in lineStr: if len(lineStr) > 4: #checks length for line in lineStr.split(','): if circline == 1: #gets value circDiam = float(line.strip("\n \r")) #draw circle drawcircle(sketcher,xPos,yPos,5*circDiam,color) circline = 0 elif circline == 0: circline = 1 if newLine == 1: newY = yPos+5*verPos #finds new end position newX = xPos+5*horPos #finds new end position sketcher.create_line(xPos, yPos, newX, newY, fill=color, width = 2) xPos = newX #adjusts end position yPos = newY #adjusts end position root.after(10, runLoop) runLoop() root.mainloop() Example of Sketches Attachments: Computer Power Supply Introduction A lot of us have an old desktop computer we don't want anymore and it's good to re-use components. You'll find in each standard sized desktop, an ATX power supply. It's a standardized form factor for AC-to-DC power conversion with +3, +5, +12, and sometimes -5 and -12 VDC rails. If you look on the side, there is a sticker that will say what power it is rated to output. Most power supplies are rated for usage in the range of 300 Watts to 600 Watts. High end ones go from 700 to 1200 Watts. That's not "toy" power. It can be dangerous and these things don't seem to have any fuses or anything in them. I melted a +5VDC wire for a few seconds when it accidentally contacted a ground. You could definitely start a fire with this and maybe hurt yourself. That being said, it is nice to have a nearly unlimited and somewhat well regulated power supply for no cost. You can get them new for about 20$ too, which seems like a good deal due to the variety of standardized voltages available.

It is not entirely straightforward to use these. They don't just turn on when they get power and there is no button for it. It is designed to be managed by an ATX compatible motherboard on computer. Basically, you need to short a specific pin to ground with a specific resistance (or use a potentiometer, like I did).

Parts

• A computer (ATX) power supply
• A potentiometer OR an appropriate resistor and toggle button
• A green LED for the power indicator
• A red LED to show that the supply is on
• Two resistors (220-1000 Ohm) for the LEDs
• Binding Posts (optional)
• Voltage Regulators (optional)

Planning

If you want to add a button or potentiometer to turn it on, you'll need to cut a hole for it in the back. Potentiometers and certain buttons work nice because all you need to do is drill a hole of the right size and you can easily attach it with a nut and lock washer.

If you want some indicator LEDs, you'll have to drill holes for those too - probably on the front somewhere. You will need to open up the power supply and look carefully for a place to drill that won't damage the components.

Wiring

The Standard Connectors

ColorSignalPinPinSignalColor
Orange +3.3 V 1 13 +3.3 V Orange
sense Brown
Orange +3.3 V 2 14 −12 V Blue
Black Ground 3 15 Ground Black
Red +5 V 4 16 Power on Green
Black Ground 5 17 Ground Black
Red +5 V 6 18 Ground Black
Black Ground 7 19 Ground Black
Grey Power good 8 20 Reserved N/C
Purple +5 V standby 9 21 +5 V Red
Yellow +12 V 10 22 +5 V Red
ATX 20 Pin Connector ( Wikipedia )

The standard connectors, ATX and Molex, will both be removed and reorganized into something more like a lab power supply than one that can only power a desktop computer.

The ATX connector has 20 pins and a clip on one side:

Note that the pins in the photo are flipped horizontally from the pins according to wikipedia. Also, some of those pins don't match up. The colors seem to be accurate though. You may wish to look for a version of the ATX table that matches the configuration of your power supply.

If you have that smaller orange/brown wire on Pin 13, just cut it off completely. It is not very useful and just confuses things. On mine, it was orange, so I kept thinking it was supposed to be 3.3V.

The ON Switch

Turning the power supply on isn't entirely straightforward. It won't just turn on when you plug it in.

You can touch the green wire, which is the "Power On" (aka PS_ON) to a Ground (black wire). However, it needs a specific resistance. Otherwise it will just turn on for a fraction of a second and then turn back off. Rather than just trying out what resistance it needed, I used a potentiometer. If you want to use a button, I'd still use the potentiometer to experimentally determine the range of values you can use for the resistance.

Be very sure when testing how to turn it on that you don't shock yourself, or have any of the leads touching each other. At this point, you should only really need to have cut the green wire out of the 20 pin ATX molex connector and any of the black grounds.

Clearly, I did not do a great job of soldering this thing. It was actually my first time ever soldering, and it works. Minor victory.

The green wire can go on either end of the potentiometer (pot) - all it will change is which end has higher resisistance. The ground goes on the middle pin. I would guess you could probably even flip these wires and it would still work.

If you want to use a button, try turning on the power supply with the potentiometer a few times. Get a multimeter / voltmeter and see what the resistance is of the potentiometer between the two pins you are using. That will be the resistance you should target between your button.

Power LEDs

If you want an LED to be on whenever the powersupply has power - even if the power supply isn't on - you can use the purple wire, which is labelled as the +5V standby pin. So, just connect an LED+resistor combination that can deal with a 5VDC connection.

To mount the LED, I did not use any sort of clips or brackets. I just drilled a hole and taped the wires so the LED should stay in place. It isn't fool proof or professional looking, but it gets the job done.

This is the most creative part of the project. You can drill holes, use the existing hole, or try to wedge them through the grill of the plate. I opted to try them all. I wanted to have the most seperation between each of the different types of leads.  This allowed me to also label them.

There are definitely some much more elegant solutions to this, such as using banana / twist mounts ( binding posts ) instead of exposing the wires. The case could also be removed altogether and simply put the power supply directly into your project's chasis.

DJI ESC and Brushless Motor

Indrocution

These parts are designed to be used in a quadrocopter. They are sold as replacement parts to pre-built quadrocopters, but work well as interchangable parts. This is documention on the specs and how to use the parts, since none is really provided.

I have modelled these parts in Creo Parametric. However, since I am using the student edition, it would likely be uselless to anyone who wants the part for their own project since it supposedly will only work with other student licenses. Furthermore, I'm not sure the license would even allow me to do that. I am not aware of a reason why I can't show you the results of the model like diagrams and renders though.

DJI ESC

Note that I did not bother to dimension the lump where the wires come out because the shape is so irregular and varies between each individual one.

Specs

The name on the label is simply 18A. You could call it a DJI Opto-coupled electronic speed controller.

CurrentVoltageBattery
Compatibility
Frequency
Response
18 A 11.1-14.8V 3S-4S LiPo 30-450 Hz

When I weighed it I found it is 0.815 oz. The ESC outputs 3.33V on the red wire.

Signal

Some ESCs have a complicated (and undocumented) startup routine. It allows them to calibrate their input signal range. In this case, we have such control over our controller that it is substantially easier to calibrate the controller than the ESC.

According to the DJI wiki on the ESC, as well as the sticker on the actual device, it can accept signals from 30 Hz to 450 Hz. The Arduino Servo library outputs a pulse every 20ms, which translates to a frequency of 50Hz, which is within the allowable range. To set the speed, use Servo.writeMicroseconds( pulseDuration ). According to Arduino, a servo can be set to no speed with a by passing the parameter a value of 1000 uS, and full speed by passing 2000. However, according to this wiki specifically about ESCs, the range is typically from 500 uS to 2500 uS. This specific one seems to take a range from 1150 to 1950.

Motor

Specs

The full name as far as I can tell, is: DJI Brushless outrunner 2212/920K Motor F330-550.

rpm/VShaft3S Battery / Prop4S Battery / PropCurrentMax Current
920 kv 8mm 11.1V / 10x4.5 14.7V / 8x4.5 15-25A 30A

I have weighed it myself at 1.980 oz (56.1321 grams). It is about 1.25 inches in diameter, and about 2 inches tall.

Lift Test

I tested the signal ranges for the ESC and the corresponding lifts for two kinds of DJI propellers.

Parts

• DJI 30A ESC
• DJI 2212 920kv motor
• An aluminum/steel beam about 1/8" thick to mount the motor to
• 2 to 4 M3 (3mm) screws
• 2 to 4 M3 (3mm) lock washers
• Drill
• Drill bits capable of drilling into metal
• 9/64" drill bit for outer mounting holes
• 9/32" drill bit for inner shaft hole
• A power supply capable of 11-13v at 18 A
• A block of wood (2x4, 4x4, etc)
• DJI 8045 (8" diameter) propeller
• DJI 1045 (10" diameter) propeller
• A food scale or more scientific scale with a range of about 0-8lb
• Clamps

Wiring

The ESC outputs a well regulated 3.33V on the small red wire, which is enough for some microcontrollers and Arduinos, but not the Arduino Uno or Mega. So the Arduino Uno would need a seperate power souce. The data pin can be any pin that the Servo library can use.

Setup

Using a desktop computer power supply capable of powering 36A of 12V to power the ESC and motor, it should have more than sufficient power. The testing rig was a very quickly put together device just intended to keep it firmly in place on the scale. The scale was not a particularly accurate one either, but it worked reasonably well.

Results

The most lift achieved on the 10" propeller was 1 pound. The most lift achieved on the 8" propeller was about 3/4 of a pound with a servo delay of 1950 microseconds.

A lot about the test is not perfectly accurate for my needs. It used 12v instead of 11.1. Also, the scale that was used was not very accurate either since the readings could be easily read wrong by an ounce. Furthermore, due to the off-center nature of the mounting bracket, the weight on the scale may not have been read perfectly well. Still, it provides a good guideline for how much the combination of parts can lift.

Most importantly, the 4 by 4 blocked more of the airflow than any chassis would, so one might expect to get even more lift than these measurements.

It also should be observed that there was no additional lift after 1900 on the 10" propeller, but the 8" one saw an increase. This could suggest that the ESC is reaching its amperage limit of 18A.

The motor was noticably warm after the 10" test, but was not at all during the 8" test. This leads me to believe that the 8" propeller would be substantially more efficient, if you don't need the extra lift.

Test Code

#include <Servo.h>  Servo myservo;  // create servo object to control a servo  int val;    // variable to read the value from the analog pin  void setup() {   Serial.begin(9600);  myservo.attach(9);  // attaches the servo on pin 9 to the servo object }  void loop() {   val = 1050;  delay(500);  myservo.writeMicroseconds(val);  Serial.println(val);}
Attachments:

Divergence Meter

Backstory

I want to make a divergence meter. A divergence meter is not a real thing. It's a fictional device from Steins;Gate to tell if the worldline (timeline) has changed substantially from an original world line (the alpha) - following the time travel theory popularized by John Titor. If you've never seen the show, you might still be interested in how to wire up a longer string of displays to get 8 digits instead of being stuck with just 4.

A Nixie Tube
Wiki Commons
Richard Bartz

I'm not actually going to build a very accurate one. It turns out that that many Nixie tubes are kind of expensive (about $100), but you really should use them if you want to maintain authenticity. There are plenty of other tutorials on how to make one with nixie tubes, and you can even buy an offical one, which admittedly does not look all that accurate. The show specifically references Nixie tubes' cool factor, so it's really an important detail. Also, it is obviously not going to be able to actually measure the attractor field, so it will instead randomly make up divergence values at random times. Also, according to canon, the divergence meter should cycle random numbers on the display quickly while the divergence number is changing for about a second. To somewhat replicate its purpose, this system will change divergence number about once a day or perhaps longer. One could look to the divergence meter to try making a small change in their life. Very infrequently, the divergence number should jump to something above 1%. Larger numbers could be cause for celebration or trying larger changes in one's life. Parts Serial Seven Sgement Displays Sparkfun / OpenSegment If you choose to build yours with nixie tubes, your parts list will vary greatly from this, since you will also have to wire each segment to up seperately to your microcontroller, but also need to worry about power management. Nixie tubes need high voltage and low current, so switching segments on and off might require something like a high power shift register, or a logic level shifter to protect your Arduino microcontroller. • 2x OpenSegment Serial Displays 20mm or 12.8mm (Sparkfun,$17ea)
• Hard Wire (8 segments)
• Arduino Micro without headers (Adafruit, $23) • Enclosure for two displays side by side and a micro • should leave micro USB port exposed or use a panel mount The above parts list assumes you will want to solder the whole thing together permanently. The total cost for this project, without using nixie tubes, is only about$57 plus whatever you use to make the case with. It is substantially safer, cheaper, and easier to make.

Wiring

The wiring here could not be easier if you're using the serial seven segment displays. The nixie tubes, however, will be nightmarish and will probably require making your own printed circuit board (PCB) to keep your sanity and to keep the device compact.

Only hook up the first seven segment display. If you keep both on, you will have a problem due to the fact that both of the displays have the same address. So, both would react to the same commands. Fortunately, it can be easily changed with the right command code (0x80). By default, the address is 0x71. Change the address of the first display to just about anything but that. So, with just one display connected, run this:

#include <Wire.h>void setup() {  Wire.beginTransmission( 0x71 );   // Start I2C transmission to first display  Wire.write( 0x80 );               // I2C Address Config command
Wire.write( 0x42 );               // Set 7-bit address to 0x42  Wire.endTransmission();           // Stop I2C transmission}void loop() {}

Connections

You will probably want to solder these connections instead of using headers and pins because it will save space and cost. However, it will make the changes somewhat more permanent. On the bright side, if you later decide you don't want a divergence meter, you can actually have it display just about anything - like the time perhaps.

To hook up these displays, simply connect the SDA and SCL pins on the Arduino Micro microcontroller to the SDA pin on the SDA and SCL pins on the display respectively. Likewise, connect the 5V from the Arduino to the + on the display, and the GND on the Arduino to the - on the display. Again, only do this for the one display.

Once you change the address of the first display, you can actually hook the other display up to the same wires. It might sound weird at first, but that's how i2c works. Check the sparkfun tutorial and see for yourself. The smaller serial7segment displays have a +,-,SDA, and SCL pin on each side to pass the connection through to the next one easily. You can do this yourself with just some wire though.

Code

#define DISPLAY1 0x71
#define DISPLAY2 0x42

#include <Wire.h>

unsigned long divergence = 337187; //or 409031
// displayed as:         0.337187
//Given a string, i2cSendString sends the first four characters over i2c
void i2cSendString(char *toSend, int addr) {
Wire.beginTransmission(addr); // transmit to device #1
for(byte x = 0 ; x < 4 ; x++) {  // for each of the 4 characters
Wire.write(toSend[x]);         // Send the character from the array
}
Wire.endTransmission();          // Stop I2C transmission
}

void updateDisplay() {
char first[5];
char second[5];

snprintf( first , 5, "%05d", divergence / 10000UL ); //pad with 0
snprintf( second, 5, "%05d", divergence % 10000UL ); //pad with 0

//move the second number to first place, then replace with space
//it looks weird, but that's how the divergence meter is in the show
first[0] = first[1];
first[1] = ' ';

i2cSendString(first , DISPLAY1);
i2cSendString(second, DISPLAY2);

Serial.print(first);
Serial.println(second);

// write the decimal place
Wire.beginTransmission(DISPLAY1); // transmit to device #1
Wire.write( 0x77 );               // send decimal command
Wire.write( 1 << 3 );             // send the place using bitshift
Wire.endTransmission();           // Stop I2C transmission
}

void newNumber() {
// small percent chance to break divergence barrier
if ( random(0, 100) < 5 ) {
divergence = random(1000000UL, 1409031UL);
}

divergence = random(0UL, 999999UL);

updateDisplay();
}

// when the divergence number changes
// the divergence meter cycles numbers randomly
// until a new number stabilizes

void changingNumber() {
for( int cycle = 0; cycle < 100; ++cycle ) {
divergence = random(0, 9999999UL);
updateDisplay();
delay( 30 );
}
}

void setup() {

// read the noise for some randomness
// noise will cause the call to randomSeed() to generate
// different seed numbers each time the sketch runs.
// randomSeed() will then shuffle the random function.

Serial.begin(19200); //for debugging
}

//increase this if you're impatient to change the divergence number
#define tdivider 10000UL
void loop() {

changingNumber();
newNumber();

unsigned long wait = random(43200000UL , 604800000UL)  / tdivider;
Serial.print("Waiting ");
Serial.print(wait);
Serial.println(" milliseconds before number change");

delay(wait); // 12 hours to a week

} 

Octobot Chassis

Introduction

Octobot is the name of the robotic chassis that I do most of my testing on. It got it's name because it originally had eight wires sticking out because of the motors.

The picture to the right shows it in its unfinished form.  The front two wheels were removed and exchanged for a ball caster for manuverability.

Once completed, the chassis makes an excellent inexpensive platform for an Arduino robot.

The Making of Octobot

Parts:

• 4WD Chassis and Motors from Jameco
• 1" Ball Caster from Pololu
• 3/8" Spacer
• Screwdriver
• Drill
• Solder and Soldering Iron
• Wires

Construction:

As can be seen, Octobot started out with four motors and four wheels. It was quickly discovered that this was not desirable if the robot had to perform tight turns. Therefore, Octobot was altered to have two wheels and a ball caster.

This required getting a 3/8" spacer made from aluminum to get a more appropriate height. Holes had to be drilled in the chassis to align with the ball casters holes. The alterations were fairly quick and simple to do. This is a cheaper alternative to some of the robotic platforms available.

Uses

Octobot is used to test most of the code I post if it directly pertains to use on a robot. Two arduinos can easily be attached via standoffs to the top of Octobot.

Simple Security System

Introduction

Who hasn't wanted to monitor what goes on when they aren't there. When I was little, I was always curious about whether or not anyone was going into my room and would have loved a camera monitoring system. It may even be a good idea to have a simple security setup for an apartment.

This tutorial shows how to set up a PIR sensor along with a small TTL camera and an SD card to capture images whenever there is movement in the monitored area.

The necessary libraries are: SoftwareSerial (for the camera) and SDFat (for the SD card).

Parts

• PIR Sensor
• SD Card Breakout Board
• SD Card
• 2 10k Resistors
• 3 other Resistors (I'm not sure if size matters, but mine were all above 1k)
• Wires
• Arduino

Code

Arduino

Below is the code:

/***************************
PIR Motion Detection - Camera Capture

by Jennifer Case
5/21/2013

Parts:
-PIR Sensor
-SD Card Breakout Board
-TTL Camera

Pin 2,3 - Camera
Pin 8 - PIR Sensor
Pin 10 - CS/D3
Pin 11 - CMD
Pin 12 - D0
Pin 13 - CLK
****************************/
#include <SoftwareSerial.h>
#include <SdFat.h>

//SD Card
SdFat sd;
SdFile myFile;
int picCnt = 0;

//Camera
byte incomingbyte;
SoftwareSerial cameraSerial = SoftwareSerial(2, 3);   //Configure pin 2 and 3 as soft serial port
uint8_t MH,ML;
boolean EndFlag=0;

//Declare pins
const int chipSelect = 10;
int pirPin = 8;

void setup() {
Serial.begin(19200); //start serial
cameraSerial.begin(38400); //start serial with camera

// Initialize SdFat or print a detailed error message and halt
// Use half speed like the native library.
// change to SPI_FULL_SPEED for more performance.
if (!sd.begin(chipSelect, SPI_HALF_SPEED)) sd.initErrorHalt();

SendResetCmd(); //allows camera to take pictures
delay(3000); //delay necessary for camera reset
}

void loop() {

//when val is HIGH, there is motion -> take pictures
if (val == HIGH) {
//create title for images
char photoTitle[25] = {};
sprintf(photoTitle, "pic%d.txt", picCnt);
//Serial.println(photoTitle);

//make sure file can be created, otherwise print error
if (!myFile.open(photoTitle, O_RDWR | O_CREAT | O_AT_END)) {
sd.errorHalt("opening photoTitle.txt for write failed");
}

//Serial.print("Writing to file...");

SendTakePhotoCmd(); //take photo
delay(200); //delay to make sure there is no drop in the data
//Serial.println("Start pic");

while(cameraSerial.available()>0) {
incomingbyte=cameraSerial.read(); //clear unneccessary serial from camera
}
byte b[32];

while(!EndFlag) {
j=0;
k=0;
count=0;
SendReadDataCmd(); //command to get picture from camera

delay(75); //delay necessary for data not to be lost
while(cameraSerial.available()>0) {
k++;
if((k>5)&&(j<32)&&(!EndFlag)) {
b[j]=incomingbyte;
if((b[j-1]==0xFF)&&(b[j]==0xD9))
EndFlag=1; //when end of picture appears, stop reading data
j++;
count++;
}
}

for(j=0;j<count;j++) { //store picture into file
if(b[j]<0x10)
myFile.print("0");
myFile.print(b[j], HEX);
}
myFile.println();
}

StopTakePhotoCmd(); //stop this picture so another one can be taken
EndFlag = 0; // reset flag to allow another picture to be read
//Serial.println("End of pic");

myFile.close(); //close file
//Serial.println("done.");
//Serial.println();

picCnt++; //increment value for next picture
}
}

//Send Reset command
void SendResetCmd() {
cameraSerial.write((byte)0x56);
cameraSerial.write((byte)0x00);
cameraSerial.write((byte)0x26);
cameraSerial.write((byte)0x00);
}

//Send take picture command
void SendTakePhotoCmd() {
cameraSerial.write((byte)0x56);
cameraSerial.write((byte)0x00);
cameraSerial.write((byte)0x36);
cameraSerial.write((byte)0x01);
cameraSerial.write((byte)0x00);

a = 0x0000; //reset so that another picture can taken
}

void FrameSize() {
cameraSerial.write((byte)0x56);
cameraSerial.write((byte)0x00);
cameraSerial.write((byte)0x34);
cameraSerial.write((byte)0x01);
cameraSerial.write((byte)0x00);
}

MH=a/0x100;
ML=a%0x100;

cameraSerial.write((byte)0x56);
cameraSerial.write((byte)0x00);
cameraSerial.write((byte)0x32);
cameraSerial.write((byte)0x0c);
cameraSerial.write((byte)0x00);
cameraSerial.write((byte)0x0a);
cameraSerial.write((byte)0x00);
cameraSerial.write((byte)0x00);
cameraSerial.write((byte)MH);
cameraSerial.write((byte)ML);
cameraSerial.write((byte)0x00);
cameraSerial.write((byte)0x00);
cameraSerial.write((byte)0x00);
cameraSerial.write((byte)0x20);
cameraSerial.write((byte)0x00);
cameraSerial.write((byte)0x0a);

a+=0x20;
}

void StopTakePhotoCmd() {
cameraSerial.write((byte)0x56);
cameraSerial.write((byte)0x00);
cameraSerial.write((byte)0x36);
cameraSerial.write((byte)0x01);
cameraSerial.write((byte)0x03);
}

This code sets up the SD card, reads from the PIR sensor and then takes pictures while there is motion. Everytime a picture is taken, the name of the file is incremented up.

Python

The Python code from the camera tutorial has been revamped to allow for multiple photos to be processed at a time. This is set up to work with the naming given in the above code. The user may still have to adjust the range depending on the number of photos.

#!/usr/bin/python
# open file
import binascii

count = 0

for count in range (0,4):

f = open ("PIC%d.txt" % (count),"r")
nf = open("IMAGE%d.jpg" % (count),"wb")

while 1:
d = c.strip()
#print (c)
#print (d)
if not c:
break
nf.write(binascii.a2b_hex(bytes(d, "ascii")))

# Close the file
f.close()
nf.close()

Sample Images

Here are a couple proof of concept images showing that the camera and motion detection works.

Attachments:

Inverted Pendulum Controls

Introduction

Balancing an inverted pendulum is the typical example when demonstrating a control system. A weight on an arm above the rotation pivot is an unstable system. It has one stable point when the weight is perfectly balanced. If the weight is slightly on either side of this point it will begin to move away from this stable point. On the other hand, a weight on an arm below the rotation pivot is a stable system. The weight is stable at the point exaclty below the pivot as well, but if it is moved slightly away from this point it will move back towards it.

I have built a simulation using web standards like JavaScript and HTML so you can observe the impact different PID controls have on an inverted pendulum. You can modify the gains of the proportional, integral, and derivative controls to test how each component works. The simulation is optimized to be used with Chrome and Firefox, but has a limited set of features available for Internet Explorer.

A screenshot of the simulation. Click to do your own simulations.

Simulation Usage

The simulation is designed to be very easy to use. Here are some steps to run your own test.

1. Modify the control gains, initial states, and properties of the system
2. Click "simulate".
3. Observe the behavior of the system. In particular, watch the direction the forces are being applied by the controller, and how well the weight is being balanced.
4. When done, click "stop". The simulation can be run for several minutes - much longer and it may become unresponsive due to the accumulation of many data points.
5. A graph will appear. You can show and hide variables by clicking on them in the legend. You can also download the data in CSV format by clicking the "download" button. If using Internet Explorer, the "show" button must be used, and data can be copied manually.
6. Click "reset". Repeat (go to step 1).

Dynamics

The true diferential equations for the motion of the system can be found on Wikipedia.

In some derivations, the centripital acceleration force due to the angular velocity is left out. The dynamics in this simulation does not rule out this term. However, it may be safe to neglect the term when designing the control system due to the fact that a balanced pendulum should have low velocity.

To simulate these dynamics, the second derivatives are isolated to one side of each equation. Then each second order equation is turned into two first order equations. Finally, they are solved using numerical integration by using the RK4 method.

PID Controls

 Angle Error 15° 1.1% 30° 4.5% 60° 17.3% 90° 36.3% 120° 58.6% 150° 80.9% 180° 100.0%

The control system used in the simulation is a basic, linearized control system. Using the small angle approximation that , the control system can be simplified. While the approximation holds true for angles close to zero (sin0 = 0), at larger values the approximation gets worse.

Note that θ = 0 when the pendulum is upright.

The control system then becomes:

F = - kP * θ - kD * ω - kI * ∫ θ dt

The gains then can be modified depending on the properites like mass and pendulum length.

A systematic way to iteratively improve a design is to try a pair of values and observe if there is overshoot and how much. Overshoot is the overcorrection for an error - or the amplitude "wobble" on the bar. Also, observe the settle time - or the time it takes for a the system to reach its steady-state. The settle time is the time it takes for the bar to stop wobbling.

If there is a lot of overshoot, try decreasing kP or increasing kD. If there is a long settle time, try increasing kP. kI is used to eliminate steady-state error. This would be if the pendulum were to balance for a prolonged period at a position other than vertical.

Udoo

Basic Features

The Udoo is relatively pricey, but has some great features and is relatively well documented. They bill themselves as a "Raspberry Pi + Arduino", but that is selling themselves a little short. Anyone could plug an Arduino into the USB port of a Raspberry Pi. The ARM processor is faster and more capable than the Raspberry Pi, but also has the same pinout as the Arduino Due with the exception of a few missing pins like the analog ones. Additionally, there is an Arduino Due-like processor that has full access to the same pins. That's right. Both processors can access the same pins. They can access different ones at the same time, or even send signals to each other if you configure it that way.

It features an ARMv7 processor, not ARMv6 like the Raspberry Pi. The newer instruction set means each core of the ARM processor is significantly (2x) faster at many tasks. More importantly, it is the same instruction set supported by popular Linux distrobutions like Ubuntu and Android. The Raspberry Pi's ARMv6 processor is pretty much restricted to the Raspbian Debian derivative.

It took exactly 1 week for SECO USA to ship to my address in the US. They shipped it from Italy, apparently. There are very few details on shipping deadlines and they never notified me that they even shipped the thing, let alone give me a tracking number. Even after I received it, the order was still listed as "processing". I contacted their support, which responded fairly qucikly, and this is apparently standard procedure. The shipping method is referred to as "FCA shipping", but it was fullfilled through UPS. As a result of the lack of transparency and risk of delay due to the fact that it came from oversees, I might suggest purchasing the Udoo from Maker Shed instead if you are in the US.

I would not recommend using the SD card in their accessories package. It is class 4 and is noticably slower than a class 10. Painfully slow, actually. The udoo itself is actually plenty fast, and capable of using the class 10 speed. I ran a benchmark using palimptest (gnome-disk-utility) and a $14 16GB class 10 SanDisk SDSDQU-016G-AFFP-A managed to pull 21.1 MB/s read with a 1ms access time, which is well above even the class 10 spec. Benchmarks run on class 4's tend to be more in the 4-5MB/s. One of the great features of the Udoo is its speed, so I don't know why you would skimp on such an important feature. A lot of class 4's are actually more expensive than 10's depending on where you buy them. I thought it might even be worthwhile going for one of the Extreme lines that promise 90MB/s. It turns out the speed is limited to 21.4MB/s on the uSD card, so the socket can't quite deliver the same speed of SATA. All that being said, the accessories package has some other cool things like a SATA power adapter and an SSD would be many times faster than any uSD card. I wonder if it is SATA I, II, or III though. The documentation does not seem to say anywhere, but this page has a benchmark where the SATA plug goes up to 110 MB/s read on the same palimptest. Setup The documentation on udoo.org/getting-started are maybe a little too basic for most users. All you really need are to download the latest Ubuntu image from here, and write it to the uSD card using these instructions. Here are some packages I would strongly recommend: sudo apt-get install bash-completion python-smbus Here are some others I would also recommend: • midori: A lightweight web browser • guvcview: Way to preview webcams to see if they are working and tinker with settings • sparkleshare: Dropbox-like syncronization using git • vlc: plays everything • qalqulate-gtk: great calculator that even does algebra • minicom: command line viewer for RX/TX serial Add some swap Probably one of the most limiting features of the Udoo is its 1GB RAM. It is pretty easy to run out of memory pretty quickly with the default installation, and when you do things get bad fast. Processes start crashing until there is some free memory again. What is slightly less bad than that? Writing some of that memory to the slow SD card. If you do this a lot, the SD card may slowly degrade since there is a limited number of writes you can do. Still, it seems preferable to the alternative which is guaranteed crashing. So, look into adding a swapfile or a swap partition. Partitions are easy to do in gparted. It's pretty easy to do and well documented elsewhere, so I won't do it here. Pinout Pin Muxing To change the pin mode you have to change a .h file in the kernel source recompile the kernel. This can be done according to the manual, but they leave out exactly how to compile a kernel, which is maybe the more daunting of the two tasks. There is a pretty detailed tutorial here. wget https://github.com/UDOOboard/Kernel_Unico/archive/master.zipunzip master.zipcd Kernel_Unico-masternano arch/arm/mach-mx6/board-mx6qd_seco_UDOO.h # modify the pinout heresudo apt-get install ncurses-devmake menuconfigmake -j5 uImage modules # makes using 5 coressudo cp /boot/uImage /boot/uImage.bak #make a backup copy of the old uImagesudo cp arch/arm/boot/uImage /boot/uImagesudo make modules_installsudo rm /usr/src/linux && sudo ln -s . /usr/src/linux The actual compile process took less than 15 minutes for me. Probably less, but I wasn't watching that closely. The wget and unzip may have actually taken longer if that's even possible. Networking Notes The wireless chip is actually on the same USB hub as the two external ports. This means that the wireless speeds will be limited to USB 2.0 speeds and that it will compete for the same USB throughput as other devices like thumb drives, hard drives, or webcams. The wireless chip that comes on it is actually wireless 802.11 N compatible, but probably is not capable of any great speed increase. It is a Ralink RT5370 with the USB ID 148f:5370. This chip may be able to go into Master / Access Point mode, but I have not managed to do so yet. Somewhere when considering purchasing the Udoo I saw that the gigabit ethernet speeds were somewhat limited. I did a speedtest on my 100mbit line and was able to get 90-80 Mbit/s. I did not test a full gigabit LAN connection. Installing OpenCV The default OpenCV is quite old due ot the two year old Ubuntu release, and has a couple bugs in it. As a result, download the newest version from the website: sudo apt-get install gcc g++ cmake build-essential libgtk2.0-dev pkg-config python-dev libavcodec-dev libavformat-dev libswscale-dev libjpeg-dev libpng-dev libtiff-dev libjasper-dev libavcodec-dev libavformat-dev libswscale-dev libdc1394-22-dev libxine-dev libgstreamer0.10-dev libgstreamer-plugins-base0.10-dev libv4l-devwget # find url from http://opencv.org/downloads.htmltar -xvf opencv-*cd ???/releasecmake -D CMAKE_BUILD_TYPE=RELEASE -D CMAKE_INSTALL_PREFIX=/usr/local -D BUILD_NEW_PYTHON_SUPPORT=ON -D BUILD_EXAMPLES=ON -D ENABLE_NEON ON ..make -j 5 # will probably take a very long time (hour+)sudo make install Attachments: Udoo Benchmarks Introduction Each test was run on an Udoo with a Quad core while X.org was running and a Chromium window was open. The additional load, for the most part, is not important because most these benchamarks only test one of the cores of the udoo at a time. Only the 7zip test ran accross all cores. To compare the benchmarks to those of the Raspberry Pi (wiki), I used this package (zip). Also compare to my Angstrom BeagleBone Black test . Dhrystone (no compiler optimization) At 1,048,252 dhrystones per core, each core with the unoptimized compile is about as fast as a Raspberry Pi with an optimized compile. $ gcc dhry_1.c dhry_2.c dhry.h cpuidc.c -lpthread -lrt -o dhry$./dhry ########################################## Dhrystone Benchmark, Version 2.1 (Language: C or C++) Optimisation Opt 3 32 Bit Register option not selected 10000 runs 0.03 seconds 100000 runs 0.15 seconds 200000 runs 0.20 seconds 400000 runs 0.38 seconds 800000 runs 0.76 seconds 1600000 runs 1.51 seconds 3200000 runs 3.05 seconds Final values (* implementation-dependent): Int_Glob: O.K. 5 Bool_Glob: O.K. 1 Ch_1_Glob: O.K. A Ch_2_Glob: O.K. B Arr_1_Glob[8]: O.K. 7 Arr_2_Glob8/7: O.K. 3200010 Ptr_Glob-> Ptr_Comp: * 98680 Discr: O.K. 0 Enum_Comp: O.K. 2 Int_Comp: O.K. 17 Str_Comp: O.K. DHRYSTONE PROGRAM, SOME STRING Next_Ptr_Glob-> Ptr_Comp: * 98680 same as above Discr: O.K. 0 Enum_Comp: O.K. 1 Int_Comp: O.K. 18 Str_Comp: O.K. DHRYSTONE PROGRAM, SOME STRING Int_1_Loc: O.K. 5 Int_2_Loc: O.K. 13 Int_3_Loc: O.K. 7 Enum_Loc: O.K. 1 Str_1_Loc: O.K. DHRYSTONE PROGRAM, 1'ST STRING Str_2_Loc: O.K. DHRYSTONE PROGRAM, 2'ND STRING From File /proc/cpuinfo Processor : ARMv7 Processor rev 10 (v7l) processor : 0 BogoMIPS : 790.52 processor : 1 BogoMIPS : 790.52 processor : 2 BogoMIPS : 790.52 processor : 3 BogoMIPS : 790.52 Features : swp half thumb fastmult vfp edsp neon vfpv3 CPU implementer : 0x41 CPU architecture: 7 CPU variant : 0x2 CPU part : 0xc09 CPU revision : 10 Hardware : SECO i.Mx6 UDOO Board Revision : 63012 Serial : 021111d4dbc7884d From File /proc/version Linux version 3.0.35 (udoo@ubuntu) (gcc version 4.4.4 (4.4.4_09.06.2010) ) #1 SMP PREEMPT Sat Oct 12 14:05:30 CEST 2013 Nanoseconds one Dhrystone run: 953.97 Dhrystones per Second: 1048252 VAX MIPS rating = 596.61 Dhrystone (O3 compiler optimization) With over 2,809,990 dhrystones per second, each core of the Udoo quad is essentially three Raspberry Pi's. I thought maybe it was using the extra cores, and ran the test while using top to see that it is, in fact, only using 100% CPU (not 300%+). The BeagleBone Black with Ubuntu ran at 3,319,960 dhrystones per second, so it is roughly as fast as that. gcc dhry_1.c dhry_2.c dhry.h cpuidc.c -lpthread -lrt -O3 -o dhry ubuntu@imx6-qsdl:~/Downloads/Raspberry_Pi_Benchmarks/Source Code$ ./dhry
##########################################

Dhrystone Benchmark, Version 2.1 (Language: C or C++)

Optimisation    Opt 3 32 Bit
Register option not selected

10000 runs   0.01 seconds
100000 runs   0.11 seconds
200000 runs   0.08 seconds
400000 runs   0.14 seconds
800000 runs   0.29 seconds
1600000 runs   0.57 seconds
3200000 runs   1.15 seconds
6400000 runs   2.28 seconds

Final values (* implementation-dependent):

Int_Glob:      O.K.  5  Bool_Glob:     O.K.  1
Ch_1_Glob:     O.K.  A  Ch_2_Glob:     O.K.  B
Arr_1_Glob[8]: O.K.  7  Arr_2_Glob8/7: O.K.     6400010
Ptr_Glob->              Ptr_Comp:       *    94584
Discr:       O.K.  0  Enum_Comp:     O.K.  2
Int_Comp:    O.K.  17 Str_Comp:      O.K.  DHRYSTONE PROGRAM, SOME STRING
Next_Ptr_Glob->         Ptr_Comp:       *    94584 same as above
Discr:       O.K.  0  Enum_Comp:     O.K.  1
Int_Comp:    O.K.  18 Str_Comp:      O.K.  DHRYSTONE PROGRAM, SOME STRING
Int_1_Loc:     O.K.  5  Int_2_Loc:     O.K.  13
Int_3_Loc:     O.K.  7  Enum_Loc:      O.K.  1
Str_1_Loc:                             O.K.  DHRYSTONE PROGRAM, 1'ST STRING
Str_2_Loc:                             O.K.  DHRYSTONE PROGRAM, 2'ND STRING

From File /proc/cpuinfo
Processor	: ARMv7 Processor rev 10 (v7l)
processor	: 0
BogoMIPS	: 790.52

processor	: 1
BogoMIPS	: 790.52

processor	: 2
BogoMIPS	: 790.52

processor	: 3
BogoMIPS	: 790.52

Features	: swp half thumb fastmult vfp edsp neon vfpv3
CPU implementer	: 0x41
CPU architecture: 7
CPU variant	: 0x2
CPU part	: 0xc09
CPU revision	: 10

Hardware	: SECO i.Mx6 UDOO Board
Revision	: 63012
Serial		: 021111d4dbc7884d

From File /proc/version
Linux version 3.0.35 (udoo@ubuntu) (gcc version 4.4.4 (4.4.4_09.06.2010) ) #1 SMP PREEMPT Sat Oct 12 14:05:30 CEST 2013

Nanoseconds one Dhrystone run:       355.87
Dhrystones per Second:              2809990
VAX  MIPS rating =                  1599.31


Linpack (no compiler optimization)

$gcc linpack.c cpuidc.c -lpthread -lrt -o linpack$ ./linpack

##########################################
Unrolled Double Precision Linpack Benchmark - Linux Version in 'C/C++'

Optimisation Opt 3 32 Bit

norm resid      resid           machep         x[0]-1          x[n-1]-1
1.7    7.41628980e-14   2.22044605e-16  -1.49880108e-14  -1.89848137e-14

Times are reported for matrices of order          100
1 pass times for array with leading dimension of  201

dgefa      dgesl      total     Mflops       unit      ratio
0.02323    0.00169    0.02492      27.55     0.0726     0.4451

10 times   0.04 seconds
100 times   0.17 seconds
200 times   0.26 seconds
400 times   0.51 seconds
800 times   1.00 seconds
Overhead for 1 matgen      0.00125 seconds

Calculating matgen/dgefa passes for 1 seconds
10 times   0.12 seconds
20 times   0.22 seconds
40 times   0.43 seconds
80 times   0.86 seconds
160 times   1.70 seconds
Passes used         93

Times for array with leading dimension of 201

dgefa      dgesl      total     Mflops       unit      ratio
0.00961    0.00030    0.00991      69.32     0.0289     0.1769
0.01040    0.00034    0.01074      63.91     0.0313     0.1919
0.01037    0.00032    0.01069      64.24     0.0311     0.1909
0.01002    0.00031    0.01033      66.50     0.0301     0.1844
0.00975    0.00052    0.01026      66.92     0.0299     0.1832
Average                                66.18

Overhead for 1 matgen      0.00135 seconds

Times for array with leading dimension of 200

dgefa      dgesl      total     Mflops       unit      ratio
0.00944    0.00031    0.00975      70.39     0.0284     0.1742
0.00997    0.00034    0.01031      66.61     0.0300     0.1841
0.00989    0.00030    0.01019      67.41     0.0297     0.1819
0.00970    0.00030    0.01000      68.67     0.0291     0.1786
0.00980    0.00033    0.01013      67.80     0.0295     0.1809
Average                                68.18

##########################################

From File /proc/cpuinfo
Processor	: ARMv7 Processor rev 10 (v7l)
processor	: 0
BogoMIPS	: 790.52

processor	: 1
BogoMIPS	: 790.52

processor	: 2
BogoMIPS	: 790.52

processor	: 3
BogoMIPS	: 790.52

Features	: swp half thumb fastmult vfp edsp neon vfpv3
CPU implementer	: 0x41
CPU architecture: 7
CPU variant	: 0x2
CPU part	: 0xc09
CPU revision	: 10

Hardware	: SECO i.Mx6 UDOO Board
Revision	: 63012
Serial		: 021111d4dbc7884d

From File /proc/version
Linux version 3.0.35 (udoo@ubuntu) (gcc version 4.4.4 (4.4.4_09.06.2010) ) #1 SMP PREEMPT Sat Oct 12 14:05:30 CEST 2013

Unrolled Double  Precision       66.18 Mflops


Linpack (O3 compiler optimization)

gcc linpack.c cpuidc.c -lpthread -lrt -O3 -o linpack
./linpack

##########################################
Unrolled Double Precision Linpack Benchmark - Linux Version in 'C/C++'

Optimisation Opt 3 32 Bit

norm resid      resid           machep         x[0]-1          x[n-1]-1
1.7    7.41628980e-14   2.22044605e-16  -1.49880108e-14  -1.89848137e-14

Times are reported for matrices of order          100
1 pass times for array with leading dimension of  201

dgefa      dgesl      total     Mflops       unit      ratio
0.01608    0.00050    0.01658      41.41     0.0483     0.2961

10 times   0.02 seconds
100 times   0.10 seconds
200 times   0.09 seconds
2000 times   0.78 seconds
4000 times   1.68 seconds
Overhead for 1 matgen      0.00042 seconds

Calculating matgen/dgefa passes for 1 seconds
10 times   0.06 seconds
100 times   0.48 seconds
200 times   0.94 seconds
400 times   1.87 seconds
Passes used        213

Times for array with leading dimension of 201

dgefa      dgesl      total     Mflops       unit      ratio
0.00427    0.00017    0.00444     154.65     0.0129     0.0793
0.00430    0.00017    0.00448     153.36     0.0130     0.0800
0.00420    0.00017    0.00438     156.94     0.0127     0.0781
0.00417    0.00018    0.00435     158.01     0.0127     0.0776
0.00417    0.00018    0.00435     157.88     0.0127     0.0777
Average                               156.17

Overhead for 1 matgen      0.00038 seconds

Times for array with leading dimension of 200

dgefa      dgesl      total     Mflops       unit      ratio
0.00392    0.00017    0.00409     168.04     0.0119     0.0730
0.00395    0.00017    0.00412     166.69     0.0120     0.0736
0.00392    0.00017    0.00408     168.12     0.0119     0.0729
0.00394    0.00017    0.00411     167.12     0.0120     0.0734
0.00395    0.00017    0.00412     166.63     0.0120     0.0736
Average                               167.32

##########################################

From File /proc/cpuinfo
Processor	: ARMv7 Processor rev 10 (v7l)
processor	: 0
BogoMIPS	: 790.52

processor	: 1
BogoMIPS	: 790.52

processor	: 2
BogoMIPS	: 790.52

processor	: 3
BogoMIPS	: 790.52

Features	: swp half thumb fastmult vfp edsp neon vfpv3
CPU implementer	: 0x41
CPU architecture: 7
CPU variant	: 0x2
CPU part	: 0xc09
CPU revision	: 10

Hardware	: SECO i.Mx6 UDOO Board
Revision	: 63012
Serial		: 021111d4dbc7884d

From File /proc/version
Linux version 3.0.35 (udoo@ubuntu) (gcc version 4.4.4 (4.4.4_09.06.2010) ) #1 SMP PREEMPT Sat Oct 12 14:05:30 CEST 2013

Unrolled Double  Precision      156.17 Mflops


7zip  with Chromium Running

This is the only test that uses all the cores of the Udoo. It also never seems to complete. I suspect it is running out of ram - mostly due to X running. At the time of the test only 219MB was free. And no swap was available by - which is the defualt configuration. As one would expect, since each core is roughly as fast as a BeagleBone Black, the total speed for the Udoo for both compressing and decompressing is about four times as fast as the BeagleBone Black.

$7z b 7-Zip 9.20 Copyright (c) 1999-2010 Igor Pavlov 2010-11-18 p7zip Version 9.20 (locale=C,Utf16=off,HugeFiles=on,4 CPUs) RAM size: 621 MB, # CPU hardware threads: 4 RAM usage: 434 MB, # Benchmark threads: 4 Dict Compressing | Decompressing Speed Usage R/U Rating | Speed Usage R/U Rating KB/s % MIPS MIPS | KB/s % MIPS MIPS 22: 1216 254 465 1183 | 30151 362 752 2720 23: 1164 248 478 1186 | 30379 368 754 2780 Killed  7zip without Chromium running This time, it did not crash at the same place. It is worth noting that it is a little faster now that Chromium is not using a little CPU. Also, it slows down as it got to the test where it crashed - probably due to the need to free some RAM. $ 7z b

7-Zip 9.20  Copyright (c) 1999-2010 Igor Pavlov  2010-11-18
p7zip Version 9.20 (locale=C,Utf16=off,HugeFiles=on,4 CPUs)

RAM size:     621 MB,  # CPU hardware threads:   4
RAM usage:    434 MB,  # Benchmark threads:      4

Dict        Compressing          |        Decompressing
Speed Usage    R/U Rating  |    Speed Usage    R/U Rating
KB/s     %   MIPS   MIPS  |     KB/s     %   MIPS   MIPS

22:    1207   260    451   1174  |    31465   379    749   2839
23:    1215   267    464   1237  |    30984   378    750   2835
24:    1148   264    468   1234  |    30059   374    745   2788
----------------------------------------------------------------
Avr:          263    461   1215               377    748   2821
Tot:          320    604   2018


OpenSSL

\$ openssl speedOpenSSL 1.0.0e 6 Sep 2011
built on: Wed Oct  5 01:45:02 UTC 2011
options:bn(64,32) rc4(ptr,char) des(idx,cisc,16,long) aes(partial) blowfish(ptr)
compiler: cc -fPIC -DOPENSSL_PIC -DZLIB -DOPENSSL_THREADS -D_REENTRANT -DDSO_DLFCN -DHAVE_DLFCN_H -DL_ENDIAN -DTERMIO -O2 -Wa,--noexecstack -g -Wall
The 'numbers' are in 1000s of bytes per second processed.
type             16 bytes     64 bytes    256 bytes   1024 bytes   8192 bytes
md2                  0.00         0.00         0.00         0.00         0.00
mdc2                 0.00         0.00         0.00         0.00         0.00
md4               7761.79k    26911.62k    75214.93k   135954.32k   178506.41k
md5               5767.57k    19209.05k    50070.10k    81085.73k   101173.93k
hmac(md5)         6381.72k    21288.94k    53009.49k    84140.37k   101087.64k
sha1              5666.52k    16888.08k    37025.76k    52359.00k    58607.51k
rmd160            5257.78k    14787.15k    30770.00k    42600.47k    48376.64k
rc4              62741.19k    68218.54k    70962.26k    70447.09k    70686.04k
des cbc          15914.89k    16795.56k    17455.62k    17476.95k    17304.57k
des ede3          6203.65k     6306.68k     6338.39k     6370.38k     6292.45k
idea cbc             0.00         0.00         0.00         0.00         0.00
seed cbc         17832.68k    19928.66k    19854.59k    19216.84k    18967.42k
rc2 cbc          10840.32k    11225.97k    11317.79k    11660.63k    11661.06k
rc5-32/12 cbc        0.00         0.00         0.00         0.00         0.00
blowfish cbc     24167.36k    26446.88k    27283.46k    27385.97k    27343.57k
cast cbc         21879.96k    23476.25k    23563.43k    23602.86k    22880.26k
aes-128 cbc      16743.73k    17882.61k    18444.54k    18474.12k    18795.02k
aes-192 cbc      14343.86k    15459.49k    15857.10k    15878.14k    15483.75k
aes-256 cbc      12639.34k    13298.28k    13605.58k    13706.53k    13602.02k
camellia-128 cbc    22846.73k    24616.23k    25983.91k    26494.98k    25978.78k
camellia-192 cbc    18236.58k    20065.58k    20567.55k    20692.31k    20728.49k
camellia-256 cbc    18566.37k    20146.07k    20573.10k    20700.84k    20499.11k
sha256            3800.08k     8691.37k    15218.29k    18623.56k    20044.37k
sha512             914.51k     3706.11k     5185.64k     7120.61k     7908.75k
whirlpool         1377.65k     2809.03k     4500.46k     5302.20k     5497.99k
aes-128 ige      16060.83k    17553.19k    17875.99k    17982.54k    17846.46k
aes-192 ige      13971.60k    15051.37k    15428.15k    15460.35k    15398.23k
aes-256 ige      12274.63k    13041.07k    13216.33k    13419.59k    13413.03k
sign    verify    sign/s verify/s
rsa  512 bits 0.002148s 0.000174s    465.5   5738.0
rsa 1024 bits 0.010869s 0.000507s     92.0   1971.4
rsa 2048 bits 0.062687s 0.001641s     16.0    609.3
rsa 4096 bits 0.402000s 0.005541s      2.5    180.5
sign    verify    sign/s verify/s
dsa  512 bits 0.001732s 0.001985s    577.5    503.8
dsa 1024 bits 0.004978s 0.005795s    200.9    172.6
dsa 2048 bits 0.015997s 0.019006s     62.5     52.6
sign    verify    sign/s verify/s
160 bit ecdsa (secp160r1)   0.0009s   0.0040s   1111.7    250.9
192 bit ecdsa (nistp192)   0.0010s   0.0046s    971.7    215.2
224 bit ecdsa (nistp224)   0.0014s   0.0064s    739.7    156.3
256 bit ecdsa (nistp256)   0.0018s   0.0091s    566.4    109.9
384 bit ecdsa (nistp384)   0.0039s   0.0207s    257.0     48.4
521 bit ecdsa (nistp521)   0.0088s   0.0454s    114.0     22.0
163 bit ecdsa (nistk163)   0.0036s   0.0082s    277.7    122.6
233 bit ecdsa (nistk233)   0.0069s   0.0158s    144.4     63.3
283 bit ecdsa (nistk283)   0.0105s   0.0296s     95.0     33.8
409 bit ecdsa (nistk409)   0.0242s   0.0691s     41.3     14.5
571 bit ecdsa (nistk571)   0.0599s   0.1616s     16.7      6.2
163 bit ecdsa (nistb163)   0.0037s   0.0090s    271.5    111.3
233 bit ecdsa (nistb233)   0.0073s   0.0182s    136.5     54.9
283 bit ecdsa (nistb283)   0.0110s   0.0343s     91.0     29.2
409 bit ecdsa (nistb409)   0.0255s   0.0815s     39.3     12.3
571 bit ecdsa (nistb571)   0.0622s   0.1911s     16.1      5.2
op      op/s
160 bit ecdh (secp160r1)   0.0034s    290.2
192 bit ecdh (nistp192)   0.0040s    252.3
224 bit ecdh (nistp224)   0.0055s    183.3
256 bit ecdh (nistp256)   0.0078s    127.6
384 bit ecdh (nistp384)   0.0171s     58.6
521 bit ecdh (nistp521)   0.0377s     26.5
163 bit ecdh (nistk163)   0.0040s    251.8
233 bit ecdh (nistk233)   0.0078s    128.5
283 bit ecdh (nistk283)   0.0146s     68.6
409 bit ecdh (nistk409)   0.0364s     27.4
571 bit ecdh (nistk571)   0.0851s     11.8
163 bit ecdh (nistb163)   0.0046s    217.4
233 bit ecdh (nistb233)   0.0091s    109.6
283 bit ecdh (nistb283)   0.0166s     60.4
409 bit ecdh (nistb409)   0.0415s     24.1
571 bit ecdh (nistb571)   0.0970s     10.3