Plane | Final Static Prototype [Documentation]

Let me preface this by saying that I am immensely proud of this work. The work up to here is very special and I can only hope that my work going forward is as good as this.

So I’m calling this the “Final Static Prototype” because it’s pretty damn complete for being prototype and it does not move. I intend on making a moving, non-flying prototype sometime in the future. Let’s start out with the video:

Now an explanation for each of the components starting with the controller.

It’s pretty much the same deal I’ve been using this entire time. The program works as follows.

1. The computer sends a delay value and a cycle number

2. The arduino receives that data

3. The arduino sends the debug switch value, the x and y values of the joystick and the pot value.

4. The program renders that information on the program.

Here’s the controller’s source:

//include/define
#include <string.h> // we'll need this for subString
#define MAX_STRING_LEN 20 // like 3 lines above, change as needed.

//Mux control pins
int s0 = 8;
int s1 = 9;
int s2 = 10;
int s3 = 11;
int SIG_pin = 0;

//Shift Register Pins
int SER_Pin = 5; //pin 14 on the 75HC595
int RCLK_Pin = 6; //pin 12 on the 75HC595
int SRCLK_Pin = 7; //pin 11 on the 75HC595
#define number_of_74hc595s 1 //How many of the shift registers - change this
#define numOfRegisterPins number_of_74hc595s * 8 //do not touch
boolean registers[numOfRegisterPins];

//serial stuff
const char EOPmarker = '.'; //This is the end of packet marker
char serialbuf[32]; //This gives the incoming serial some room. Change it if you want a longer incoming.

//other pin setup
int joystick_x;
int joystick_y;
int pot_1;

int debug_switch = 4;

//vars
int sample_delay;
int cycle_number;

void setup(){
 //mux setup
 pinMode(s0, OUTPUT);
 pinMode(s1, OUTPUT);
 pinMode(s2, OUTPUT);
 pinMode(s3, OUTPUT);
 digitalWrite(s0, LOW);
 digitalWrite(s1, LOW);
 digitalWrite(s2, LOW);
 digitalWrite(s3, LOW);

 //shift register setup
 pinMode(SER_Pin, OUTPUT);
 pinMode(RCLK_Pin, OUTPUT);
 pinMode(SRCLK_Pin, OUTPUT);
 pinMode(0, INPUT);
 clearRegisters();
 writeRegisters();

 //other pin setup
 pinMode(debug_switch, INPUT);

 Serial.begin(115200);
}

void loop(){ //start of main loop -------------------------------------------
 //delay(25);
 pin_remap();
 if (Serial.available() > 0) {
 static int bufpos = 0;
 char inchar = Serial.read();
 if (inchar != EOPmarker) {
 serialbuf[bufpos] = inchar;
 bufpos++;
 }
 else {
 serialbuf[bufpos] = 0; //restart the buff
 bufpos = 0; //restart the position of the buff

sample_delay = atoi(subStr(serialbuf, "," , 1));
 cycle_number = atoi(subStr(serialbuf, "," , 2));

 serial_handshake();
 //delay(100);
 }
 }

 delay(sample_delay);

} //end of main loop --------------------------------------------------------

//start of logic functions ------------------------------------------------
void serial_output_deploy(){
 Serial.print("0");
 Serial.print(",");
 Serial.print(joystick_x);
 Serial.print(",");
 Serial.print(joystick_y);
 Serial.print(",");
 Serial.print(pot_1);
 Serial.print(",");
 Serial.print(sample_delay);
 Serial.print(",");
 Serial.print(cycle_number);

 Serial.println("");
}

void serial_output_debug(){
 Serial.print("1");
 Serial.print(", ");
 Serial.print("Joystick X Axis: ");
 Serial.print(joystick_x);
 Serial.print(" , ");
 Serial.print("Joystick Y Axis: ");
 Serial.print(joystick_y);
 Serial.print(" , ");
 Serial.print("Speed Potentiometer: ");
 Serial.print(pot_1);
 Serial.print(" , ");
 Serial.print("Amount of delay between cycles: ");
 Serial.print(sample_delay);
 Serial.print(" , ");
 Serial.print("Cycle Number:");
 Serial.print(cycle_number);

 Serial.println("");
}

void pin_remap(){
 joystick_x = map(readMux(15), 0, 1023, 180, 0);
 joystick_y = map(readMux(14), 0, 1023, 0, 180);
 pot_1 = map(readMux(13), 0, 1023, 0, 179);
}

void serial_handshake(){
 if (digitalRead(debug_switch) == HIGH){
 serial_output_debug();
 setRegisterPin(1, HIGH);
 setRegisterPin(2, LOW);
 writeRegisters();
 }

 if (digitalRead(debug_switch) == LOW){
 serial_output_deploy();
 setRegisterPin(2, HIGH);
 setRegisterPin(1, LOW);
 writeRegisters();
 }
}
 //end of logic functions --------------------------------------------------
void clearRegisters(){
 for(int i = numOfRegisterPins - 1; i >= 0; i--){
 registers[i] = LOW;
 }
}

void writeRegisters(){
 digitalWrite(RCLK_Pin, LOW);
 for(int i = numOfRegisterPins - 1; i >= 0; i--){
 digitalWrite(SRCLK_Pin, LOW);
 int val = registers[i];
 digitalWrite(SER_Pin, val);
 digitalWrite(SRCLK_Pin, HIGH);
 }
 digitalWrite(RCLK_Pin, HIGH);
}

//set an individual pin HIGH or LOW
void setRegisterPin(int index, int value){
 registers[index] = value;
}

int readMux(int channel){
 int controlPin[] = {s0, s1, s2, s3};
 int muxChannel[16][4]={
 {0,0,0,0}, //channel 0
 {1,0,0,0}, //channel 1
 {0,1,0,0}, //channel 2
 {1,1,0,0}, //channel 3
 {0,0,1,0}, //channel 4
 {1,0,1,0}, //channel 5
 {0,1,1,0}, //channel 6
 {1,1,1,0}, //channel 7
 {0,0,0,1}, //channel 8
 {1,0,0,1}, //channel 9
 {0,1,0,1}, //channel 10
 {1,1,0,1}, //channel 11
 {0,0,1,1}, //channel 12
 {1,0,1,1}, //channel 13
 {0,1,1,1}, //channel 14
 {1,1,1,1} //channel 15
 };

//loop through the 4 sig
 for(int i = 0; i < 4; i ++){
 digitalWrite(controlPin[i], muxChannel[channel][i]);
 }

//read the value at the SIG pin
 int val = analogRead(SIG_pin);

//return the value
 return val;
}

char* subStr (char* input_string, char *separator, int segment_number) {
 char *act, *sub, *ptr;
 static char copy[MAX_STRING_LEN];
 int i;

 strcpy(copy, input_string);

for (i = 1, act = copy; i <= segment_number; i++, act = NULL) {

 sub = strtok_r(act, separator, &ptr);
 if (sub == NULL) break;
 }
 return sub;
}

Now for the output simulator (eventually the plane)

This works like the controller with the “handshake” protocol as described above, but it writes to the servos and then sends sensor values. Here’s that source:

//include/define
#include <string.h> // we'll need this for subString
#define MAX_STRING_LEN 20 // like 3 lines above, change as needed.
#include <LiquidCrystal.h> //we'll need this for the lcd
LiquidCrystal lcd(22, 24, 26, 28, 32, 34); //pins for the lcd, I set it up using the ladyada tutorial.
#include <Servo.h>

//inputs
int debug_switch = 7;

//outputs
Servo left_servo;
Servo right_servo;
Servo esc;
int esc_pwm = 6;
int debug_led = 11;
int deploy_led = 12;

//numbers
int left_servo_pos;
int right_servo_pos;
int current;

//serial stuff
const char EOPmarker = '.'; //This is the end of packet marker
char serialbuf[32]; //This gives the incoming serial some room. Change it if you want a longer incoming.

//shift register setup
int SER_Pin = 8; //pin 14 on the 75HC595
int RCLK_Pin = 9; //pin 12 on the 75HC595
int SRCLK_Pin = 10; //pin 11 on the 75HC595
#define number_of_74hc595s 1 //How many of the shift registers - change this
#define numOfRegisterPins number_of_74hc595s * 8 //do not touch
boolean registers[numOfRegisterPins];

void setup(){
 //lcd.begin(16, 2);
 left_servo.attach(3);
 right_servo.attach(5);
 esc.attach(6);

 current = 0;

 pinMode(debug_switch, INPUT);
 pinMode(1, INPUT);

 pinMode(debug_led, OUTPUT);
 pinMode(deploy_led, OUTPUT);
 pinMode(SER_Pin, OUTPUT);
 pinMode(RCLK_Pin, OUTPUT);
 pinMode(SRCLK_Pin, OUTPUT);
 pinMode(esc_pwm, OUTPUT);

// for(int i = 0; i < 180; i += 1){
// esc.write(i);
// Serial.println(i);
// delay(15);
// }

 clearRegisters();
 writeRegisters();

 Serial.begin(115200); //changing this to other speeds has not been tested using this meathod
}

void loop() {
 if (Serial.available() > 0) {
 //lcd.clear();
 static int bufpos = 0;
 char inchar = Serial.read();
 if (inchar != EOPmarker) {
 serialbuf[bufpos] = inchar;
 bufpos++;
 }
 else {
 serialbuf[bufpos] = 0; //restart the buff
 bufpos = 0; //restart the position of the buff

 if(digitalRead(debug_switch) == HIGH){
 debug();
 }

 if(digitalRead(debug_switch) != HIGH){
 deploy();
 }
 out_deploy();
 }

 }

}
// below is just function logic, which I do not fully understand. but it works.
char* subStr (char* input_string, char *separator, int segment_number) {
 char *act, *sub, *ptr;
 static char copy[MAX_STRING_LEN];
 int i;

 strcpy(copy, input_string);

for (i = 1, act = copy; i <= segment_number; i++, act = NULL) {

 sub = strtok_r(act, separator, &ptr);
 if (sub == NULL) break;
 }
 return sub;
}

void clearRegisters(){
 for(int i = numOfRegisterPins - 1; i >= 0; i--){
 registers[i] = LOW;
 }
}

void writeRegisters(){
 digitalWrite(RCLK_Pin, LOW);
 for(int i = numOfRegisterPins - 1; i >= 0; i--){
 digitalWrite(SRCLK_Pin, LOW);
 int val = registers[i];
 digitalWrite(SER_Pin, val);
 digitalWrite(SRCLK_Pin, HIGH);
 }
 digitalWrite(RCLK_Pin, HIGH);
}

//set an individual pin HIGH or LOW
void setRegisterPin(int index, int value){
 registers[index] = value;
}

void spinto(int target) {

 //digitalWrite(led2, LOW);

 while(current > target){
 Serial.println(current);
 esc.write(current);
 delay(15);
 current--;
 }

 while(current < target){
 Serial.println(current);
 esc.write(current);
 delay(15);
 current++;
 }
}

void debug(){
 setRegisterPin(2, HIGH);
 setRegisterPin(1, LOW);
 writeRegisters();

 left_servo_pos = atoi(subStr(serialbuf, ",", 1));
 lcd.write("Lft Servo:");
 lcd.write(subStr(serialbuf, ",", 1)); //witres the first bit of content before the first comma (or other seperator) to the lcd
 left_servo.write(left_servo_pos);

 lcd.setCursor(0, 1);

 right_servo_pos = atoi(subStr(serialbuf, ",", 2));
 lcd.write("Rgt Servo:"); //this signifies that the first seperation has occured
 lcd.write(subStr(serialbuf, ",", 2)); //same thing as 2 lines above, but with the second parts. this can be repeated
 right_servo.write(right_servo_pos);

 analogWrite(esc_pwm, atoi(subStr(serialbuf, ",", 3)));
}

void deploy(){
 setRegisterPin(2, LOW);
 setRegisterPin(1, HIGH);
 writeRegisters();

 left_servo.write(atoi(subStr(serialbuf, ",", 1)));
 right_servo.write(atoi(subStr(serialbuf, ",", 2)));
 analogWrite(esc_pwm, atoi(subStr(serialbuf, ",", 3)));
}

void out_deploy(){
 Serial.print(analogRead(0));
 Serial.print(",");
 Serial.print(analogRead(1));
 Serial.print(",");
 Serial.print(analogRead(2));

 Serial.println("");
}

//esologic.com
//Thanks to http://arduino.cc/forum/index.php?topic=119429

The visual basic program which I’m calling “Vehicle Companion” can be found here in all of it’s glory. The picture below also shows the whole system.

Now all I need is the money to make this thing wireless because I’ve got a way to make it into a moving prototype using materials I already have. I’ll put a donate button somewhere on this website eventually if you want to help me out.

Thanks for reading.

Encoding A LOT of video in linux | [Documentation]

For my Raspberry Pi Media Server to be able to stream to mobile (a topic I haven’t yet covered here) I need to convert ALL of the video in my family’s 700+ file, 400+ gb, media collection to H.264/MPEG-4 AVC. I recently acquired a hard drive to consolidate and store all of this hard drive on. For the past week or so I’ve been making some progress in converting the video. On my windows tower I’ve been using the program Format Factory to convert the video. I’m running into a few problems with this. For one, my windows computer is my main machine, and multithread converting really bottlenecks it. It also takes a long time – having to watch it while it does it’s thing waiting for it to convert instead of just going to the next set of files is annoying. I could just convert

So I’ve decided to get back into python and write a program that will perfect the conversion process. Like in my PiScanner project, I’ll be using an existing program within python and my code will automate the process.

Goals are as follows:

1. Convert the video

2. Make sets of folders for the video

3. Have it all done on the external HDD

4. Have it be more “efficient” than the setup I’m running now. I.E be able to be on all the time – which shouldn’t be a problem as the server you’re viewing this website on is on all time time and I can just run the script here.

5. Make the end program useable for anyone.

WordPress installation on ubuntu 10.04

There are probably a million tutorials out there to do this, but as I’m doing it for the second time, I figure that I should probably write it down.

First thing’s first, make sure you’re all updated:

sudo apt-get update

Then install lamp

sudo apt-get install lamp-server^

and run through the install process. Make sure you write all of that info down.

Then download wordpress. Assuming they still have their download architecture the same as the time I’m writing this, you can just use this command.

wget http://www.wordpress.org/latest.tar.gz

And unzip this file.

tar -xzvf latest.tar.gz

You should see a LOT of stuff unzipping.

Then remove the tarball

rm latest.tar.gz

Now you need to create a database.

mysql -u WHATEVER YOUR USERNAME IS -p YOUR PASSWORD
mysql> CREATE DATABASE wordpress;
mysql> GRANT ALL PRIVILEGES ON wordpress_risp.* to "AUSERNAME"@"localhost"
#hit enter and make a new line
 -> IDENTIFIED BY "password";
FLUSH PRIVILEGES;
EXIT

Write down this information.

Next move your wordpress folder to where it’s going to be seen by the web, in my case /opt/bitnami/wordpress/risp

mv wordpress /opt/bitnami/wordpress/risp

rename the file “wp-config-sample.php” to “wp-config.php”

mv wp-config-sample.php wp-config.php

edit it using your favorite text editor, in my case vim

vi wp-config.php

Follow the instructions in the document to add your MySQL DB stuff that you established earlier.

At this point you’re pretty much done. Navigate you localhost/wp-admin/install.php in your favorite browser to set it all up.


To be able to upload images, you will need to run the following command:

 sudo chown -R 755 www-data:www-data /var/www

To be able to use custom permalinks within wordpress, we’ll need to make a couple modifications. The first is modify the apahce2 virtual host settings with:

sudo nano /etc/apache2/sites-enabled/000-default

Change the /opt/bitnami/wordpress/ settings so AllowOverride None is set to all like so:

We will also need to give the proper permissions of apache to the .htaccess (found in the root directory of your wordpress install, mine is /opt/bitnami/wordpress/) file by running the following commands:

sudo chown -v :www-data /opt/bitnami/wordpress/.htaccess
sudo chown -v 664 /opt/bitnami/wordpress/.htaccess

Note: If the file does not exist, you can create it with:

sudo nano /opt/bitnami/wordpress/.htaccess

Raspberry Pi Media Server | Streaming To Any Source Using miniDLNA [Documentation]

I’ve made some progress on the RPi Streaming Server.

To replicate this you’ll need to do the following:

1. Install miniDLNA

sudo apt-get install minidlna

2. Edit the config file to how you want it. Edit it using vim

sudo vi /etc/minidlna.conf

3. Here’s what I’m working with, and it works.

# This is the configuration file for the MiniDLNA daemon, a DLNA/UPnP-AV media
# server.
#
# Unless otherwise noted, the commented out options show their default value.
#
# On Debian, you can also refer to the minidlna.conf(5) man page for
# documentation about this file.

# Path to the directory you want scanned for media files.
#
# This option can be specified more than once if you want multiple directories
# scanned.
#
# If you want to restrict a media_dir to a specific content type, you can
# prepend the directory name with a letter representing the type (A, P or V),
# followed by a comma, as so:
#   * "A" for audio    (eg. media_dir=A,/var/lib/minidlna/music)
#   * "P" for pictures (eg. media_dir=P,/var/lib/minidlna/pictures)
#   * "V" for video    (eg. media_dir=V,/var/lib/minidlna/videos)
#
# WARNING: After changing this option, you need to rebuild the database. Either
#          run minidlna with the '-R' option, or delete the 'files.db' file
#          from the db_dir directory (see below).
#          On Debian, you can run, as root, 'service minidlna force-reload' instead.
media_dir=A,/home/pi/stream_files/media/audio
media_dir=P,/home/pi/stream_files/media/pictures
media_dir=V,/home/pi/stream_files/media/video
media_dir=/home/pi/stream_files/media

# Path to the directory that should hold the database and album art cache.
db_dir=/var/lib/minidlna

# Path to the directory that should hold the log file.
#log_dir=/var/log

# Minimum level of importance of messages to be logged.
# Must be one of "off", "fatal", "error", "warn", "info" or "debug".
# "off" turns of logging entirely, "fatal" is the highest level of importance
# and "debug" the lowest.
#log_level=warn

# Use a different container as the root of the directory tree presented to
# clients. The possible values are:
#   * "." - standard container
#   * "B" - "Browse Directory"
#   * "M" - "Music"
#   * "P" - "Pictures"
#   * "V" - "Video"
# if you specify "B" and client device is audio-only then "Music/Folders" will be used as root
#root_container=.

# Network interface(s) to bind to (e.g. eth0), comma delimited.
#network_interface=

# IPv4 address to listen on (e.g. 192.0.2.1).
#listening_ip=

# Port number for HTTP traffic (descriptions, SOAP, media transfer).
port=8200

# URL presented to clients.
# The default is the IP address of the server on port 80.
#presentation_url=http://example.com:80

# Name that the DLNA server presents to clients.
#friendly_name=

# Serial number the server reports to clients.
serial=12345678

# Model name the server reports to clients.
#model_name=Windows Media Connect compatible (MiniDLNA)

# Model number the server reports to clients.
model_number=1

# Automatic discovery of new files in the media_dir directory.
#inotify=yes

# List of file names to look for when searching for album art. Names should be
# delimited with a forward slash ("/").
album_art_names=Cover.jpg/cover.jpg/AlbumArtSmall.jpg/albumartsmall.jpg/AlbumArt.jpg/albumart.jpg/Album.jpg/album.jpg/Folder.jpg/folder.jpg/Thumb.jpg/thumb.jpg

# Strictly adhere to DLNA standards.
# This allows server-side downscaling of very large JPEG images, which may
# decrease JPEG serving performance on (at least) Sony DLNA products.
#strict_dlna=no

# Support for streaming .jpg and .mp3 files to a TiVo supporting HMO.
#enable_tivo=no

# Notify interval, in seconds.
#notify_interval=895

# Path to the MiniSSDPd socket, for MiniSSDPd support.
#minissdpdsocket=/run/minissdpd.sock

You can grab the file itself here. The only thing that’s different is where I put the media directories. The rest of the instructions are still in the .conf, it’s much simpler than mediatomb for example.

Here’s a video of the whole thing working on 3 devices!

Rpi Media Server | Testing video playback from external data source [Documentation]

So first we need to make sure I can output video files from a usb source.

I’ll be using “usbmount” and omxplayer, to get these packages make sure you’re pi’s setup correctly and run the following commands:

Note: make sure no storage devices are plugged into the usb port when you install “usbmount”

sudo apt-get install usbmount
sudo apt-get install omxplayer

Once those are installed you can start trying to play videos off of the usb drive (eventually the thumb drive  will be replaced with a large hdd

I’ll be using filezilla to transfer to and from the pi.

Check out the video below to see omxplayer in action:

Edit: The upload failed and I forgot to check on it. Come back soon for the video.

I’m choosing to debug my Pi over composite. The reason being is because I’m going to be working a lot with video outputs, and I don’t have a second hdmi ready monitor. I’m going to be using the EasyCAP usb video capture card. This will also give me the ability to record what i’m seeing as well. This 100% better / much more efficient than buying a second monitor and filming on it. Of course when this is ready for implementation, it will be plugged into a television with HDMI so the picture will be amazing.

Rpi Media Server | [Declaration]

The goal of this is to become independent from cable TV while still being able to do all of the same things we would with a cable service – I.E still consume content in the living room on the television.

It should also improve upon the experience. I want to be able to stream content from the Pi to any capable device. That list includes but is not limited to:

1. Windows XP
2. Windows 7
3. Linux Debian
4. Linux Ubuntu
5. iOS 6 (ipad)
6. iOS 5.3 (ipod Touch)
7. OSX and up
8. Android "Gingerbread" and up

I’ll be working on this post most of today, so they’ll be a few posts coming.

Plane | 3 Functional Parts and Other Ideas [Documentation]

I’ve still got no idea what i’m going to name it.  If you’ve got an idea in for the name, feel free to leave it in the comments. Actually on that note, If you’re reading this PLEASE leave a comment. I’ve had A LOT of bot traffic lately so i’m starting to really crack down on who’s a real reader or a bot.

So as you can see in the video above, I’ve gotten all 3 components working. I can use either joystick axis to control either the left or right servo independently. The potentiometer controls the value that is sent to the esc. As you can see by the code the esc signal is just a servo.write command. The controller code is identical to the last “Plane” post with the exception that the code mapped from the pot goes to 170 instead of 225. This is because I switched from a analogWrite() to a servo.write() signal.

Vehicle Code:

const char EOPmarker = '.';  //This is the end of packet marker
char serialbuf[32]; //This gives the incoming serial some room. Change it if you want a longer incoming.

#include <string.h> // we'll need this for subString
#define MAX_STRING_LEN 20 // like 3 lines above, change as needed.

#include <LiquidCrystal.h> //we'll need this for the lcd
LiquidCrystal lcd(7, 8, 9, 10, 11, 12); //pins for the lcd, I set it up using the ladyada tutorial.

#include <Servo.h>
Servo left_servo;
Servo right_servo;
Servo esc;
int esc_pwm = 6;

int left_servo_pos;
int right_servo_pos;
int current;

int prophot = 2;

int SER_Pin = 8;   //pin 14 on the 75HC595
int RCLK_Pin = 9;  //pin 12 on the 75HC595
int SRCLK_Pin = 10; //pin 11 on the 75HC595
#define number_of_74hc595s 1 //How many of the shift registers - change this
#define numOfRegisterPins number_of_74hc595s * 8 //do not touch
boolean registers[numOfRegisterPins];

void setup(){
  lcd.begin(16, 2);
  left_servo.attach(3);
  right_servo.attach(5);
  esc.attach(6);
  pinMode(prophot, INPUT);
  pinMode(esc_pwm, OUTPUT);

  current = 0;

  pinMode(SER_Pin, OUTPUT);
  pinMode(RCLK_Pin, OUTPUT);
  pinMode(SRCLK_Pin, OUTPUT);

  for(int i = 0; i < 180; i += 1){
    esc.write(i);
    Serial.println(i);
    delay(15);
  }
  esc.write(0);

  clearRegisters();
  writeRegisters();

  Serial.begin(9600); //changing this to other speeds has not been tested using this meathod
}

void loop() {

     setRegisterPin(1, HIGH);
     writeRegisters();

    if (Serial.available() > 0) { //makes sure something is ready to be read
      lcd.clear(); //clears for incoming stuff, won't clear if there isin't data to be read
      static int bufpos = 0; //starts the buffer back at the first position in the incoming serial.read
      char inchar = Serial.read(); //assigns one byte (as serial.read()'s only input one byte at a time
      if (inchar != EOPmarker) { //if the incoming character is not the byte that is the incoming package ender
        serialbuf[bufpos] = inchar; //the buffer position in the array get assigned to the current read
        bufpos++; //once that has happend the buffer advances, doing this over and over again until the end of package marker is read.
     }
      else { //once the end of package marker has been read
        serialbuf[bufpos] = 0; //restart the buff
         bufpos = 0; //restart the position of the buff

         left_servo_pos = atoi(subStr(serialbuf, ",", 1));
         setRegisterPin(1, HIGH);
         writeRegisters();
         left_servo.write(left_servo_pos);
         setRegisterPin(1, LOW);
         writeRegisters();

         lcd.setCursor(0, 1);

         right_servo_pos = atoi(subStr(serialbuf, ",", 2));
         setRegisterPin(3, HIGH);
         writeRegisters();
         right_servo.write(right_servo_pos);
         setRegisterPin(3, LOW);
         writeRegisters();

         if (digitalRead(prophot) == HIGH){
           esc.write(atoi(subStr(serialbuf, ",", 3)));
         }
         if (digitalRead(prophot) == LOW){
           esc.write(0);
         }
      }
   }
}

// below is just function logic, which I do not fully understand. but it works.
char* subStr (char* input_string, char *separator, int segment_number) {
 char *act, *sub, *ptr;
 static char copy[MAX_STRING_LEN];
 int i;

 strcpy(copy, input_string);

for (i = 1, act = copy; i <= segment_number; i++, act = NULL) {

 sub = strtok_r(act, separator, &ptr);
 if (sub == NULL) break;
 }
 return sub;
}

void clearRegisters(){
  for(int i = numOfRegisterPins - 1; i >=  0; i--){
     registers[i] = LOW;
  }
}

void writeRegisters(){
  digitalWrite(RCLK_Pin, LOW);
  for(int i = numOfRegisterPins - 1; i >=  0; i--){
    digitalWrite(SRCLK_Pin, LOW);
    int val = registers[i];
    digitalWrite(SER_Pin, val);
    digitalWrite(SRCLK_Pin, HIGH);
  }
  digitalWrite(RCLK_Pin, HIGH);
}

//set an individual pin HIGH or LOW
void setRegisterPin(int index, int value){
  registers[index] = value;
}

void spinto(int target) {

  setRegisterPin(3, HIGH);
  writeRegisters();

  while(current > target){
    //Serial.println(current);
    esc.write(current);
    delay(15);
    current--;
  }

  while(current < target){
    //Serial.println(current);
    esc.write(current);
    delay(15);
    current++;
  }

  setRegisterPin(3, LOW);
  writeRegisters();

}

//esologic.com
//Thanks to http://arduino.cc/forum/index.php?topic=119429

I’ve also been starting to think about how i’m going to take this thing to the next stage. The parts list still exists here: https://docs.google.com/spreadsheet/ccc?key=0AqD_oicSxsvmdFlPU1VPSkt6aHpoa0hqSEgwdDE2RGc  if you want to check out what i’ve done so far. I’m starting to consider materials to make the body out of. Right now the main contendor is making a frame out of aluminum dowels welded together. I’ve got a friend who can weld aluminum so assembling the frame won’t be an issue. If I go with this option, i’ll be able to cleanly mount things to the vehicle itself, and not have to worry about things splitting or cracking. It will also be heavier than if I were to go with an all foam body.

I’ve also been considering what i’m going to get for a camera for this thing. As one of the goals for this was to be able to take really nice areal videos. I’ve tentatively landed on a camera called the HackHD. The thing that’s most attractive about it is that it can do 1080p video capture AND composite video output at the same time. This is great because my original plan was to have 2 cameras – one for HD video capture, and one to transmit back to my computer. The only problem is it’s price. I could easily just hack one of those HD keychain cameras to make it operable via micro controller – but I would need to use two cameras which could be cheaper after all but powering two separate cameras would be pretty difficult.

I need to wirelessly communicate with the vehicle as well. If you look through some of the videos on my old youtube channel you can see a little RC tank that communicated via bluetooth, so I’ve got a shred of experience with homebrew wireless. Again, I’ve tentatively landed on a solution. I’ve concluded that using an Xbee system would be the most flexible while maintaining stability. It can be used as a long-range serial TxRx pipe which is what i’m prototyping with now, so the whole code’s built around that. I’d be using the XBee 1mW Wire Antenna – Series 1 (802.15.4) for the transmitter, as it’s easy to power and has an omnidirectional antenna with a range of 1 mile. While I may not be flying a mile away, I’d like to have the flexibility. I could fly in the woods, in the snow, or in the fog. To connect the xbee to the Arduino I’d probably use the SainSmart XBee USB Adapter because it’s got the UART broken out. I could use the same board to connect it to the pc as well. I could make the whole system work for around 72 dollars, which is a little high but I really want it to work well.

I’ll cover powering it in another post, but I think the next thing I get is going to be the wireless stuff. I’ve been thinking a lot about how i’m going to proto a moving vehicle, I’m thinking of some kind of fan-boat thing. Or a 3 wheeled fan propelled car.

New!

www.youtube.com/thesupertechchannel is officially going away. I will be removing all videos pertaining to content that is hosted on this website, and re-upload them to my new channel at www.youtube.com/esological. They will be reinstated on this site as well.

The why here is irrelevant. This change will slow me down a bit a first – I know i’ll be losing 90% of my audience by this change. Over time however, this change is one that needed to happen. thesupertechchannel was created in a time where I really didn’t know what content I wanted to make. I was a kid in middle school with a laptop and a copy of Sony Vegas. My analytics show that >= 50% of my views are found via search engine anyways so as long as I market myself better or at least as consistently as I did in days past, it won’t take me long to get to the point where I get ~ 100 views per video again.

I will also be able to analyze where my traffic is coming from better with this change. Hopefully I’ve some audience from this website,  and now that i’ve implemented changes in the back end of the operation of this site to be able to see where views are coming  from, I’ll be able to tailor content style to whatever posts get me the most traffic – what viewers want.

Woo!

also: minecraft, www.esologic.com:25565

Plane | Functioning Plane Output Simulator [Research]

So here are all 3 prongs of the plane code thus far. This sends data to the visual basic program, then to the visual basic program where it gets interpreted and then sent to the plane simulator Arduino. Where it is written to servos and and led.

Arduino Controller:

//Mux control pins</pre>
int s0 = 8;
int s1 = 9;
int s2 = 10;
int s3 = 11;
int SIG_pin = 0;

//Shift Register Pins
int SER_Pin = 5; //pin 14 on the 75HC595
int RCLK_Pin = 6; //pin 12 on the 75HC595
int SRCLK_Pin = 7; //pin 11 on the 75HC595
#define number_of_74hc595s 1 //How many of the shift registers - change this
#define numOfRegisterPins number_of_74hc595s * 8 //do not touch
boolean registers[numOfRegisterPins];

//other pin setup
int joystick_x;
int joystick_y;
int pot_1;

int debug_switch = 4;

void setup(){
 //mux setup
 pinMode(s0, OUTPUT);
 pinMode(s1, OUTPUT);
 pinMode(s2, OUTPUT);
 pinMode(s3, OUTPUT);
 digitalWrite(s0, LOW);
 digitalWrite(s1, LOW);
 digitalWrite(s2, LOW);
 digitalWrite(s3, LOW);

 //shift register setup
 pinMode(SER_Pin, OUTPUT);
 pinMode(RCLK_Pin, OUTPUT);
 pinMode(SRCLK_Pin, OUTPUT);
 pinMode(0, INPUT);
 clearRegisters();
 writeRegisters();

 //other pin setup
 pinMode(debug_switch, INPUT);

 Serial.begin(9600);
}
void loop(){ //start of main loop -------------------------------------------
 delay(25);
 pin_remap();

 if (digitalRead(debug_switch) == HIGH){
 serial_output_debug();
 setRegisterPin(1, HIGH);
 setRegisterPin(2, LOW);
 writeRegisters();
 }

 if (digitalRead(debug_switch) == LOW){
 serial_output();
 setRegisterPin(2, HIGH);
 setRegisterPin(1, LOW);
 writeRegisters();
 }

} //end of main loop --------------------------------------------------------
 //start of logic functions ------------------------------------------------
void serial_output(){
 Serial.print(joystick_x);
 Serial.print(" ");
 Serial.print(joystick_y);
 Serial.print(" ");
 Serial.print(pot_1);

 Serial.println("");
}

void serial_output_debug(){
 Serial.print("Joystick X Axis: ");
 Serial.print(joystick_x);
 Serial.print(" , ");
 Serial.print("Joystick Y Axis: ");
 Serial.print(joystick_y);
 Serial.print(" , ");
 Serial.print("Speed Potentiometer: ");
 Serial.print(pot_1);

 Serial.println("");
}

void pin_remap(){
 joystick_x = map(readMux(15), 0, 1023, 180, 0);
 joystick_y = map(readMux(14), 0, 1023, 0, 180);
 pot_1 = map(readMux(13), 0, 1023, 0, 255);
}
 //end of logic functions --------------------------------------------------
void clearRegisters(){
 for(int i = numOfRegisterPins - 1; i >= 0; i--){
 registers[i] = LOW;
 }
}

void writeRegisters(){
 digitalWrite(RCLK_Pin, LOW);
 for(int i = numOfRegisterPins - 1; i >= 0; i--){
 digitalWrite(SRCLK_Pin, LOW);
 int val = registers[i];
 digitalWrite(SER_Pin, val);
 digitalWrite(SRCLK_Pin, HIGH);
 }
 digitalWrite(RCLK_Pin, HIGH);
}

//set an individual pin HIGH or LOW
void setRegisterPin(int index, int value){
 registers[index] = value;
}

int readMux(int channel){
 int controlPin[] = {s0, s1, s2, s3};
 int muxChannel[16][4]={
 {0,0,0,0}, //channel 0
 {1,0,0,0}, //channel 1
 {0,1,0,0}, //channel 2
 {1,1,0,0}, //channel 3
 {0,0,1,0}, //channel 4
 {1,0,1,0}, //channel 5
 {0,1,1,0}, //channel 6
 {1,1,1,0}, //channel 7
 {0,0,0,1}, //channel 8
 {1,0,0,1}, //channel 9
 {0,1,0,1}, //channel 10
 {1,1,0,1}, //channel 11
 {0,0,1,1}, //channel 12
 {1,0,1,1}, //channel 13
 {0,1,1,1}, //channel 14
 {1,1,1,1} //channel 15
 };

//loop through the 4 sig
 for(int i = 0; i < 4; i ++){
 digitalWrite(controlPin[i], muxChannel[channel][i]);
 }

//read the value at the SIG pin
 int val = analogRead(SIG_pin);

//return the value
 return val;
}
<pre>

Arduino Vehicle:

</pre>
const char EOPmarker = '.'; //This is the end of packet marker
char serialbuf[32]; //This gives the incoming serial some room. Change it if you want a longer incoming.

#include <string.h> // we'll need this for subString
#define MAX_STRING_LEN 20 // like 3 lines above, change as needed.

#include <LiquidCrystal.h> //we'll need this for the lcd
LiquidCrystal lcd(7, 8, 9, 10, 11, 12); //pins for the lcd, I set it up using the ladyada tutorial.

#include <Servo.h>
Servo left_servo;
Servo right_servo;
int esc_pwm = 6;

int left_servo_pos;
int right_servo_pos;

void setup(){
 lcd.begin(16, 2);
 left_servo.attach(3);
 right_servo.attach(5);
 pinMode(esc_pwm, OUTPUT);

 Serial.begin(9600); //changing this to other speeds has not been tested using this meathod
}

void loop() {
 if (Serial.available() > 0) { //makes sure something is ready to be read
 lcd.clear(); //clears for incoming stuff, won't clear if there isin't data to be read
 static int bufpos = 0; //starts the buffer back at the first position in the incoming serial.read
 char inchar = Serial.read(); //assigns one byte (as serial.read()'s only input one byte at a time
 if (inchar != EOPmarker) { //if the incoming character is not the byte that is the incoming package ender
 serialbuf[bufpos] = inchar; //the buffer position in the array get assigned to the current read
 bufpos++; //once that has happend the buffer advances, doing this over and over again until the end of package marker is read.
 }
 else { //once the end of package marker has been read
 serialbuf[bufpos] = 0; //restart the buff
 bufpos = 0; //restart the position of the buff

 left_servo_pos = atoi(subStr(serialbuf, ",", 1));
 lcd.write("Lft Servo:");
 lcd.write(subStr(serialbuf, ",", 1)); //witres the first bit of content before the first comma (or other seperator) to the lcd
 left_servo.write(left_servo_pos);

 lcd.setCursor(0, 1);

 right_servo_pos = atoi(subStr(serialbuf, ",", 2));
 lcd.write("Rgt Servo:"); //this signifies that the first seperation has occured
 lcd.write(subStr(serialbuf, ",", 2)); //same thing as 2 lines above, but with the second parts. this can be repeated
 right_servo.write(right_servo_pos);

 analogWrite(esc_pwm, atoi(subStr(serialbuf, ",", 3)));
 }
 }
}

// below is just function logic, which I do not fully understand. but it works.
char* subStr (char* input_string, char *separator, int segment_number) {
 char *act, *sub, *ptr;
 static char copy[MAX_STRING_LEN];
 int i;

 strcpy(copy, input_string);

for (i = 1, act = copy; i <= segment_number; i++, act = NULL) {

 sub = strtok_r(act, separator, &ptr);
 if (sub == NULL) break;
 }
 return sub;
}

//esologic.com
//Thanks to http://arduino.cc/forum/index.php?topic=119429

&nbsp;
<pre>

Visual Basic:

https://esologic.com/source/plane/Round_1/vehicle_companion/

Just download those files and you should be able to open them in the vb studio.

Spitting incoming serial data arduino and visual basic

UPDATED CODE HERE


Hello! as you can probably tell, my last post was written in a fury of incoherency, but I needed to get the code out there so it is what it is.

The main focus of this post is to showcase the arduino program. The visual basic in the video is very simple, and there will be much more on that later.

This below program will take a string of characters fed to the arduino and split them into usable parts. This is a very valuable tool for working with serial and arduino. It’s pretty well commented, but if you have any questions, PLEASE leave a comment. I’d love to see some conversation here.

const char EOPmarker = '.'; //This is the end of packet marker
char serialbuf[32]; //This gives the incoming serial some room. Change it if you want a longer incoming.

#include  // we'll need this for subString
#define MAX_STRING_LEN 20 // like 3 lines above, change as needed.

#include  //we'll need this for the lcd
LiquidCrystal lcd(7, 8, 9, 10, 11, 12); //pins for the lcd, I set it up using the ladyada tutorial.

void setup(){
 lcd.begin(16, 2);
 Serial.begin(9600); //changing this to other speeds has not been tested using this meathod
}

void loop() {
 if (Serial.available() > 0) { //makes sure something is ready to be read
 lcd.clear(); //clears for incoming stuff, won't clear if there isin't data to be read
 static int bufpos = 0; //starts the buffer back at the first position in the incoming serial.read
 char inchar = Serial.read(); //assigns one byte (as serial.read()'s only input one byte at a time
 if (inchar != EOPmarker) { //if the incoming character is not the byte that is the incoming package ender
 serialbuf[bufpos] = inchar; //the buffer position in the array get assigned to the current read
 bufpos++; //once that has happend the buffer advances, doing this over and over again until the end of package marker is read.
 }
 else { //once the end of package marker has been read
 serialbuf[bufpos] = 0; //restart the buff
 bufpos = 0; //restart the position of the buff
 lcd.write(subStr(serialbuf, ",", 1)); //witres the first bit of content before the first comma (or other seperator) to the lcd. You could also do math or anything else with these. You could use atoi to change them to integers.
 lcd.write("|separator|"); //this signifies that the first seperation has occured
 lcd.write(subStr(serialbuf, ",", 2)); //same thing as 2 lines above, but with the second parts. this can be repeated
 }
 }
}

// below is just function logic, which I do not fully understand. but it works.
char* subStr (char* input_string, char *separator, int segment_number) {
 char *act, *sub, *ptr;
 static char copy[MAX_STRING_LEN];
 int i;

strcpy(copy, input_string);

for (i = 1, act = copy; i <= segment_number; i++, act = NULL) {

sub = strtok_r(act, separator, &ptr);
 if (sub == NULL) break;
 }
 return sub;
}

//esologic.com
//Thanks to http://arduino.cc/forum/index.php?topic=119429

So for example if you inputted

[code]
123,456.
[/code]

it would output

[code]
123|separator|456
[/code]

to the lcd, or the serial monitor if you tweaked the code.

Now for the code in the video. The only different part about this is that it writes the two values to the servos.


const char EOPmarker = ‘.’; //This is the end of packet marker
char serialbuf[32]; //This gives the incoming serial some room. Change it if you want a longer incoming.

#include // we’ll need this for subString
#define MAX_STRING_LEN 20 // like 3 lines above, change as needed.

#include //we’ll need this for the lcd
LiquidCrystal lcd(7, 8, 9, 10, 11, 12); //pins for the lcd, I set it up using the ladyada tutorial.

#include
Servo left_servo;
Servo right_servo;

int left_servo_pos;
int right_servo_pos;
void setup(){
lcd.begin(16, 2);
left_servo.attach(2);
right_servo.attach(3);
Serial.begin(9600); //changing this to other speeds has not been tested using this meathod
}

void loop() {
if (Serial.available() > 0) { //makes sure something is ready to be read
lcd.clear(); //clears for incoming stuff, won’t clear if there isin’t data to be read
static int bufpos = 0; //starts the buffer back at the first position in the incoming serial.read
char inchar = Serial.read(); //assigns one byte (as serial.read()’s only input one byte at a time
if (inchar != EOPmarker) { //if the incoming character is not the byte that is the incoming package ender
serialbuf[bufpos] = inchar; //the buffer position in the array get assigned to the current read
bufpos++; //once that has happend the buffer advances, doing this over and over again until the end of package marker is read.
}
else { //once the end of package marker has been read
serialbuf[bufpos] = 0; //restart the buff
bufpos = 0; //restart the position of the buff

left_servo_pos = atoi(subStr(serialbuf, “,”, 1));
lcd.write(“Left Servo:”);
lcd.write(subStr(serialbuf, “,”, 1)); //witres the first bit of content before the first comma (or other seperator) to the lcd
left_servo.write(left_servo_pos);

lcd.setCursor(0, 1);

right_servo_pos = atoi(subStr(serialbuf, “,”, 2));
lcd.write(“Right Servo:”); //this signifies that the first seperation has occured
lcd.write(subStr(serialbuf, “,”, 2)); //same thing as 2 lines above, but with the second parts. this can be repeated
right_servo.write(right_servo_pos);
}
}
}

// below is just function logic, which I do not fully understand. but it works.
char* subStr (char* input_string, char *separator, int segment_number) {
char *act, *sub, *ptr;
static char copy[MAX_STRING_LEN];
int i;

strcpy(copy, input_string);

for (i = 1, act = copy; i <= segment_number; i++, act = NULL) {

sub = strtok_r(act, separator, &ptr);
if (sub == NULL) break;
}
return sub;
}

//esologic.com
//Thanks to http://arduino.cc/forum/index.php?topic=119429