Friday, 28 March 2014

Raspberry Pi Car Audio

Spontaneous Projects is a chronicle of all of my projects, a reference for me, and a way to prevent others from making the same mistakes. 

So I finally got myself a couple of Raspberry Pi's, so I'm trying to get my head around what they can do. 

To start off with I'm setting one up to act as an airplay speaker for my iphone, and probably a media server that plays a random selection of music. 



First thoughts

  • Using it without the SD card doesn't boot, just a black screen. 
  • I've installed Raspian, it's easy enough to set up for WiFi and general display etc. 
  • nano and leafpad work well enough as text editors
Setting up audio for the 3.5 jack not the HDMI port
amixer cset numid=3 1 
    3 2 will make it HDMI again. 
testing the output can be conducted through aplay file.wav for any wav files you can find.

Installing Shairplay

I used parts from here and here
Shairplay is an airplay emulator, and I've found installing it to be a bit of a pain, lots of older blogs and things, but nothing current.

first up, we need to update the apt-get functions, you'll probably need sudo privileges
apt-get update
apt-get upgrade

then install some basic dev dependencies for Shairplay, some may already be installed, but it can sort that out for itself.
apt-get install libssl-dev libavahi-client-dev libasound2-dev
apt-get install git libao-dev libcrypt-openssl-rsa-perl libio-socket-inet6-perl libwww-perl avahi-utils libmodule-build-perl 


Then install Perl, this might not be required, and can certainly be done later... I'll find out when I reinstall it at some stage.

cd perl-net-sdp perl Build.PL
sudo ./Build
sudo ./Build test
sudo ./Build install
cd ..


Finally we can install shairport








git clone -b 1.0-dev git://github.com/abrasive/shareport.git
cd shairport
./configure
make
make install

You'll be missing a few things, libao, PulseAudio, but they are not essential.

Run it using ./shairport -a 'NameHere'



Some Issues I had:
symptoms, Pi is visible as an Airplay device, but won't connect.
cause: lack of avahi, perl or libao, or some other dependency that is now added in the above code. I think it's the avahi mDNS, as forcing the use of tinysvcmdns causes the same issues. But I think this was caused by the lack of perl-net-sdp...

Thursday, 20 March 2014

Mechanical Movements and Ingenious Mechanisms

Spontaneous Projects is a chronicle of all of my projects, a reference for me, and a way to prevent others from making the same mistakes. 
This is a listing of a few pages that I wandered across and felt would be useful for future spontaneous projects.

I was wandering around the internet the other day, looking at crazy gears and the like... something I want to play with a bit more once I get my scroll saw back, but these were linked in the page.

These books are really interesting, out of copyright and should be useful for mechanical art pieces and the like

Five Hundred and Seven Mechanical Movements by Henry T. Brown, published 1868

Ingenious Mechanisms for Designers and Inventors Vol 1 by Franklin D. Jones, Copyright 1930
Vol 2
Vol 3
Vol 4 



The same site that hosts the Ingenious Mechanisms volumes also has a huge variety of docs, including instructions for making band saws, lathes and the like.
It's well worth a look


Wednesday, 12 March 2014

Spontaneous Etcher

Spontaneous Projects is a chronicle of all of my projects, a reference for me, and a way to prevent others from making the same mistakes.


Hole through a hatchet, masked with packing tape
Last night I was out with a friend, a bladesmith based out of Canberra, and he was discussing the need to place makers marks on blades to make a name for himself, which is easy enough on a fully forged blade using some punches when the blade is malleable. 
He's looking into doing a few cheaper blades, just ground down, so the risks of bending it, and the time consumed make punching inefficient. 

He mentioned Electroetching, using a DC current and some salt water, to remove iron ions from the blade, removing material and resulting in an etched blade. He's done a proof of concept before using a few 9v batteries, but felt that it was too dangerous, given how the batteries heated up. 









 I have a few old laptop chargers lying around, including a 19v, 4.67 A charger, that is unlikely to be all that useful for powering other things. 
So today we made up a new etcher, and tested it on a few blades; an old machete, a stainless cooking knife and a hatchet. 

By masking the area with nail polish, and scratching a design through the polish it is possible to create the design. The remaining area of the blade was protected with packing tape, while the positive electrode was clipped to the blade, and the negative attached to a ball of cotton wool soaked in a mixture of vinegar and salt.

The first design (left) was just a wordmark "Bruce !!!", and worked quite well in about 5 minutes with a heavily salted solution. However the area that was masked with polish was also etched slightly, due to uneven, or insufficient coverage. 

Emboldened we went for a more complex design, the bearded guy below, this was less successful, as the cotton ball had to be moved around to ensure good coverage, and the polish lifted in places. 



We decided to see what shape the process created below the surface with a deeper etch, and how long it would take, so a rectangle was masked out with tape, and a hole made through the machete - minimal heating of the power supply, despite working for over an hour to get through ~2mm of material in a 12x3mm rectangle. This required several cotton balls, a lot of electrolyte solution and a bit of movement to clean out the etched area occasionally. Not something that we'll want to do to blades, but a good proof of concept.

Wanting to make something a bit more practical, and test the process on a different material we tried a hatchet, cleaned up the rust a little, sanded it back, and made a design that will likely be similar to his final one, a Celtic knot, and his initials.

The photo doesn't show a lot of detail here, but the etching wasn't particularly smooth, possibly due to the design in the polish, or too aggressive a process, but it etched, and gave a recognisable mark.

The last thing to test was the behaviour of stainless steel, so a kitchen knife was etched, again the polish layer was a little thin, and we started off with no salt in the solution, but it was too slow.   Increasing the salt content increased the reaction rate, but it was still slower than the steel blades.

End result was promising, but we need to find a better way to mask consistently.

Thoughts:

  • Masking needs to be waterproof and possess high resistance
  • Masking needs to be held tight to the material
  • Timing is important, and will vary for different materials
  • A new switch is needed, and a new clamping method is desirable
Ideal masking will be plastic film, cut to shape in bulk, so either a sticker manufacturer, or one of the stamps that you can get at lincraft etc. 







Monday, 10 March 2014

Updates, and unstable flight

Spontaneous Projects is a chronicle of all of my projects, a reference for me, and a way to prevent others from making the same mistakes. 

I've ordered the programming cables for the KK2.1 and to program the transmitter, should be here in a week of three... in the mean time I've made the KK2.1 show the correct battery voltage, and I'm working on making it fly properly.


Battery Voltage

The KK board has a in built battery meter, that is meant to be fairly accurate, I haven't tested that yet as I need to replace my multimeter. Finding the information about how to wire it up is a little challenging, and apparently doing so backwards fries the board... 


The pins on the KK 2.1 are shown to the left. Note that the battery pins are inverted reletive to the buzzer, with the positive near the side of the board. 
It is not necessary to connect the negative, as the board is grounded through the ESC's and Reciever, so it is recommended that the negative pin is removed.

The positive battery wire can then be connected to the edge side pin, and you have a battery meter. By using the Battery alarm You will know when the battery is getting low, on my 3 cell (13.3v Batteries) I have the alarm set to Xv, and the motors cut out at X v







Unstable Flight

I still haven't fixed this, and now the LCD on the Board is dead, so there goes any hope of fixing it through the autolevel options.

The issue:
It gets up a little, and after a few seconds it just wobbles, and gets worse until it falls out of the sky.

Possible Causes:
  • The wind the last few days might be causing some issues
  • The board is not sending signals to the ESC's properly, or a motor is dropping out occasionally
  • The physical configuration 0-150-210 might need to be changed to 120-120-120
  • The motor mounts may be slipping around on the limbs a little, or the limbs may be shifting slightly
  • The PID settings need to be varied a bit, and then it'll fly like a dream
  • The board is getting too much vibration
What I've tried:
Waiting for a calm day is time consuming, so we'll skip past that till it happens, 

Signals to ESC's/motors, should be ok, and hard to test

The frame design shouldn't be an issue I think, it's similar to the last design, and the gyros should be able to stabilise it anyway. .

I've adjusted the auto level P gain values a little, but didn't get to stable, decreasing it certainly made it a little better, but not enough.
Further reading suggests that the PID settings elsewhere may help, this guide by FPVcentral in particular looks to be useful.

And now the LCD has died, no substantial crash or anything. The board still arms, so it looks like I just need to get a replacement screen and/or board, so I'll be doing that once I get some stable work. 


Next steps:
I'll try changing the foam and the board mounts to dampen the vibrations a little, and I might reconfigure the physical system to a 120 degree, and I'll definitely be locking the motors in place.
I have some programmers on order, so when they arrive I'll update the firmware. Other than that I think I'll be waiting until I can afford a spare board and a new LCD


It's interesting that I'm having so many issues with this, as other people rave about the stability of this board, I'll keep trying I guess, but I'm really looking forward to knowing enough about how the things work to build my own controllers, so I know what signals they are sending, where, why, and what is going on. I hate black boxes.




Saturday, 8 March 2014

Tricopter frame V2.0

Spontaneous Projects is a chronicle of all of my projects, a reference for me, and a way to prevent others from making the same mistakes. 

Given that the V1.1 frame keeps falling apart in every crash, was unstable in the air, heavy and difficult to carry I started on model 2.0. It's still made of bits and piece I had lying around, and there are a lot of improvements still to be made, but it seems to be a bit more solid. 
Just a few different options, old tent poles.

I have a lot of old aluminium tent poles lying around, that will make perfect arms, And I like the look of the foldable Tricopter design by David. The only suitable material I have though is some 3-4mm MDF... not ideal, but it'll work for a test run.
MDF with basic design, at the moment Arms are at 0, 150, 210 degrees.

Design at this point, with bolt placement



Attaching the poles is all pretty simple, on this prototype version I didn't really think about where everything else was going to go until the arms were attached, I'll do better on the next one. 
Two of the objectives of changing the design were to reduce weight, make it easier to carry and make the center of mass lower so that the tricopter is more stable. Basically, putting the battery under the frame.


I made it a little smaller

Fully packed up

Frame Only
Final Weight
v1.0
588g
1.37kg
v2.0
271g
1.04kg

I succeeded on all of these fronts, and once I get some better material for the plates I'll get it down a bit more, as well as increasing the strength and slimming the design down a bit. 

The two front arms are designed to pivot around and lock in beside the tail when not on use, this should mean that it can be packed inside some PVC pipe for transport into and out of a cave, or thrown in the back of a car. 

It's now taken a few crashes, as I still can't control it, and the frame has stood up well, so with some better materials I think it'll get even better.

Trying to keep the motors straight might be causing some of my issues, and I know some of the early ones were caused by the arms moving about. That was fixed by tying them together with shock cord... seemed to do an adequate job. 







I took a bit more time routing the wiring on this one, as I think that it'll be a platform to be tweaked rather than retired. At the moment it looks like this:
Top

Bottom


Edit: 2 hours later it looks like this


Not sure if it's the wind screwing with the auto level, but something is... I've tried dropping the P gain a little, but no cigar. Stick scaling I've seen mentioned somewhere, but seemed to do nothing... I'll post more when I get it to fly nice and stable... 


MindSumo Challanges

Spontaneous Projects is a chronicle of all of my projects, a reference for me, and a way to prevent others from making the same mistakes. 

The other day I wandered onto this interesting CV contest, via a post on LinkedIn.

Basically, they want an algorithm designed to identify Rhino's and other animals from drone footage.

The footage they provide isn't ideal, and it looks like we'll only be able to use either normal or IR at a time for the contest because we don't have synced video. The artifacts on the outer borders are also going to be a pain.

http://www.youtube.com/watch?v=1SBMxizOPtg


My basic plan at this stage is to look for things that have a different visual flow, and then cut them out to compare to a database of existing elements, which should be able to ID them as Rhino or No. Ideally it'll also track the ones it has checked, and prompt for user agreement if the match is not great, If we can also add in new animals in the same way that too would be ideal.

Looks like a fun challenge, they have no preference for language, but want it to be implemented most easily in future, but can't tell us what platform things are on... I might stick to matlab and assume not live footage as it will be easier for me.

Monday, 24 February 2014

Full Function Tests

Spontaneous Projects is a chronicle of all of my projects, a reference for me, and a way to prevent others from making the same mistakes. 

 Using the same setup as yesterday, I've changed the motor layout to Tricopter - three motors, and the servo on channel 4.

I also removed the rubber tubing to increase the strength of the joints. A few more crashes, and took the drill out to fix it up after each crash. I've now reinforced the joints with more cable ties.

Servo - Rudder control

I've increased the functionality, adding a servo to the rear motor, using an adapted method based off this one. I used the same steering mounts he recommends, but have a DS-339MG servo. I used a small piece of 5mm dowel I had lying around, and the screws from the servo. I had to place a spacer under the hinge, and found that the perfect fit was using a piece of an old sim card - but any plastic card will work.

Full Servo set up
Credit card plastic was the perfect thickness













The wiring on Tricopter is

1            2
   \        / 
      |   |
        |
        |
        3          with servo on 4. 



KK2.1 wiring, outputs on left, 1 at top



The test flights with this setup went ok: The servo popping out is now a weak point in a crash, and one of the prop nuts came loose - only indication was that one corner just would not lift properly. Testing was cut short due to low battery - looks like it runs for 20 minutes or more.


Channel Set-up
While it was charging I've modified the Rx - Flight board cabling to get my main controls (strafe) on one stick, and the ones that will mostly be set and forget on the other. 

New setup 

Left side 
Switch       - doesn't seem to transmit - kills Throttle
Dial           - Aux turn clockwise to turn on self leveling
Vertical      - Fore aft
Horizontal  - left right strafe

Right Side
Switch       - shrinks range of everything except throttle - more precision
Dial           - no purpose
Vertical     - Throttle
Horizontal  - Rudder, should be able to be trimmed and left alone ideally. 




Sunday, 23 February 2014

HK-T6A layout and mods

Spontaneous Projects is a chronicle of all of my projects, a reference for me, and a way to prevent others from making the same mistakes. 
Manufacturers Layout diagram. I chose to switch the Aileron and Rudder outputs at the Rx end to better suit my application. 







This is for a Hobby King, HK-T6A transmitter, others may or may not be different

Channels

First up, I've changed the wiring around on the Rx end so that my throttle and rudder can be on the right stick, and pretty much set and forget, while the left controls the position of the craft.

USB Programmer

The elevator channel needs to be inverted though, so I'm going to try using this method to reprogram it, as the USB programming cables are fairly hard, and expensive to get. I'll even see if Jaycar has the plug for it to make a slightly more upmarket one for repeated use.


LiPo Battery 
I then had some issues with power, it turned out to be due to flicking switch A. But I'd already decided that it was dead batteries. While I was looking for confirmation that the charging port is +12V I stumbled on a page by NejC which suggested using a 11.1v LiPo battery. Given that I bought two for the 'copter, and had one spare, they're free to reuse, and last longer, it seemed like a good idea.
I followed his directions for a bit, but I wanted to keep the AA option, so rather than replacing the lead from the main board I just soldered extensions from the battery wires to an XT60 socket, and drilled out a larger hole in the back of the battery box. The batteries I have don't fit inside the battery case, so I've modded the door to hold a velcro strap and the battery just gets attached to the back of the transmitter.
When I do another order I'll get a smaller 12v battery to use as a dedicated battery, but for the moment this works well.



Saturday, 22 February 2014

Test Flights

Spontaneous Projects is a chronicle of all of my projects, a reference for me, and a way to prevent others from making the same mistakes. 

The new props came in on Thursday, and the beast had a few trial runs today.

First - the Frame. I built this a few weeks back, but never got around to posting it. The prototype is a three limbed copter with no rudder servo. It's main purpose is to test the lifting capacity, and ensure that all of the electronics are working properly.

Tricopter top view, with bonus lens cap

I initially connected the limbs to the main plate using some rubber tubing to reduce the vibrations, both to improve the readings of the Gyros and to improve video quality when I get to that point. However they caused a weak point in the design, so I'll likely use a method similar to David's from RC Explorer for version 2.
Anti-vibration joints

Despite the huge and heavy nature of version 1, when I started it up it had enough power to lift itself, although it didn't like to do so evenly originally. A lot of the issues had to do with rotor directions, and the channels on my transmitter. Purists will probably hate me, but I intend to put the rudder and throttle on one stick, and the strafe controls on the other, which will simplify flying it as a camera platform.
At this point however a few of the channels are reversed, and apparently need to be programmed by USB, so in order to make sense, the craft needs to be flown backwards.

Anyway, tests:



And the damage so far, due to a spontaneous decision to test inside. Note to self, probably not an inside toy.
Had an argument with a laundry basket...


What I've learnt
- It seems to self level ok once it gets up, so don't try to hover down low
- I really need to fix the channels and orientation (Needs a USB programmer for the transmitter)
- Don't turn on CCPM in the board settings - I'm not sure what it does, but it stops things from working
- It needs some skids or something to land on
- Tighten the mounting bolts on the motors, otherwise they jump off and tangle the wires in a crash

Wednesday, 19 February 2014

Progress, or not

Spontaneous Projects is a chronicle of all of my projects, a reference for me, and a way to prevent others from making the same mistakes. 

Well, as far as progress over the past few weeks goes, there hasn't been a lot. A combination of 40 degree weather in Canberra and a distinct lack of funds has put a damper on things. That said, things should get more active now, as I have a lot more time, the weather has cooled off a bit, and I should be getting a few more shifts at work in the coming months.

I have ordered some left hand (CCW) propellers for the tricopter, which should come in before the weekend. Unfortunately the maiden flight underground for the beast was meant to be this weekend, but I am unable to attend, so it will be postponed for another trip.


Monday, 13 January 2014

Blogging Tools

Spontaneous Projects is a chronicle of all of my projects, a reference for me, and a way to prevent others from making the same mistakes. 

Code Blocks

This is the code block I use, it's stolen wholesale from somewhere else on the web, but I'm afraid I can't recall where. I'm still not fully happy with it, and I'll likely keep modifying it, but it works.

Open up your Blogger page, go to template, customise, Advanced > Add CSS

And add the following code block:
.code { background:#f5f8fa; background-repeat:no-repeat; border: solid #5C7B90; border-width: 1px 1px 1px 20px; color: green ; font: 13px 'Courier New', Courier, monospace; line-height: 16px; margin: 10px 0 10px 10px; max-height: 200px; min-height: 16px; overflow: auto; padding: 28px 10px 10px; width: 90%; } .code:hover { background-repeat:no-repeat;}
Apply the template to your blog and you can use it whenever you wish. I stole it wholesale from somewhere else on the web... can't recall where I'm afraid. You can vary the colours, and any of the other options as you wish.
To use it type your code in the compose window, switch to HTML and add <div class="code"> to the start of the block, and </div> to the end.

<div class="code">

#include
your code block here
# comments

</div>


Tables


Frame Only
Final Weight
v1.0
588g
1.37kg
v2.0
271g
1.04kg

<table 100="" border="1" bordercolor="#0033FF" cellpadding="3" cellspacing="0" px="" tbody="" width:=""><tbody>
<tr><td><div style="text-align: center;">
<br /></div>
</td><td><div style="text-align: center;">
Frame Only</div>
</td><td><div style="text-align: center;">
Final Weight</div>
</td></tr>
<tr><td><div style="text-align: center;">
v1.0</div>
</td><td><div style="text-align: center;">
588g</div>
</td><td><div style="text-align: center;">
1.37kg</div>
</td></tr>
<tr><td><div style="text-align: center;">
v2.0</div>
</td><td><div style="text-align: center;">
271g</div>
</td><td><div style="text-align: center;">
1.04kg<br />
<div>
<br />
</div>
</div>
</td></tr>
</tbody></table>


  • To add or remove rows: remove the entire code between <tr> and </tr> (start/stop TableRow)
  • To add or remove columns: remove cells, <td> to </td>
  • Borders only change when page is previewed
  • Cell padding is inside borders
  • Cell spacing is between cells
  • Tables in code are ugly, and Blogger doesn't keep your formatting, so it has to be redone each time



Other Tips and Tricks

  • Alt+Print Screen on a win 7 or 8 machine does a screen cap of just the active window, so you don't need to make the rest of your desktop presentable. 
  • Multiple monitors are a god-send, always.

Matlab has a GUI tool?

So, I just found out that Matlab has a GUI creation tool, so the plus/minus tool I made in post one could have been done in Matlab, with a GUI front end. This would have been a lot quicker, but probably a lot less fun, and I wouldn't have added yet another language to my repertoire.

Either way I figured I'd have a play with the GUIde, so I tacked it on to my TimedWebcam function. This is a slight improvement over the Webcam.m function, in that it is only active between specified times.

Anyway, the GUI:

Open up Matlab, and enter "guide" (GUI de)

Create a new GUI with unicontrols

Create a simple Figure, 2 variable text boxes, 2 fixed ones, and a button:


Create the figure

Set the names and captions as you want them, as well as the starting values.

It will autocreate the basic script to generate and run the GUI, all you need to do is populate it.
In this case, all it does is feed the Start time <StT> and the Final time <FiT> to the preexisting function TimedWebcam (StT,FtT) when the main button is pressed, and keep the two variables updated if the values are changed.

The script is very similar to normal Matlab code, but because it is a series (parallel?) of individual functions, you can't pass variables directly. To do so we set a guidata object called handles which passes our data. to set a variable at the text box in this form we use:

handles.StT=StT;
guidata(hObject,handles)

and to retrieve it at the button we use

StT=handles.StT;

Pretty simple once you figure it out, and there are tutorials all over the web.

Full code:



function varargout = Webcam(varargin)
% WEBCAM M-file for Webcam.fig
%      WEBCAM, by itself, creates a new WEBCAM or raises the existing
%      singleton*.
%
%      H = WEBCAM returns the handle to a new WEBCAM or the handle to
%      the existing singleton*.
%
%      WEBCAM('CALLBACK',hObject,eventData,handles,...) calls the local
%      function named CALLBACK in WEBCAM.M with the given input arguments.
%
%      WEBCAM('Property','Value',...) creates a new WEBCAM or raises the
%      existing singleton*.  Starting from the left, property value pairs are
%      applied to the GUI before Webcam_OpeningFcn gets called.  An
%      unrecognized property name or invalid value makes property application
%      stop.  All inputs are passed to Webcam_OpeningFcn via varargin.
%
%      *See GUI Options on GUIDE's Tools menu.  Choose "GUI allows only one
%      instance to run (singleton)".
%
% See also: GUIDE, GUIDATA, GUIHANDLES

% Edit the above text to modify the response to help Webcam

% Last Modified by GUIDE v2.5 13-Jan-2014 08:07:39

% Begin initialization code - DO NOT EDIT
gui_Singleton = 1;
gui_State = struct('gui_Name',       mfilename, ...
                   'gui_Singleton',  gui_Singleton, ...
                   'gui_OpeningFcn', @Webcam_OpeningFcn, ...
                   'gui_OutputFcn',  @Webcam_OutputFcn, ...
                   'gui_LayoutFcn',  [] , ...
                   'gui_Callback',   []);
if nargin && ischar(varargin{1})
    gui_State.gui_Callback = str2func(varargin{1});
end

if nargout
    [varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:});
else
    gui_mainfcn(gui_State, varargin{:});
end
% End initialization code - DO NOT EDIT


% --- Executes just before Webcam is made visible.
function Webcam_OpeningFcn(hObject, eventdata, handles, varargin)
% This function has no output args, see OutputFcn.
% hObject    handle to figure
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
% varargin   command line arguments to Webcam (see VARARGIN)

% Choose default command line output for Webcam
clc
handles.output = hObject;

% Update handles structure
guidata(hObject, handles);

% UIWAIT makes Webcam wait for user response (see UIRESUME)
% uiwait(handles.figure1);


% --- Outputs from this function are returned to the command line.
function varargout = Webcam_OutputFcn(hObject, eventdata, handles)
% varargout  cell array for returning output args (see VARARGOUT);
% hObject    handle to figure
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Get default command line output from handles structure
varargout{1} = handles.output;


% --- Executes on button press in pushbutton1.
function pushbutton1_Callback(hObject, eventdata, handles)
% hObject    handle to pushbutton1 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
clc
StT=handles.StT;
FiT=handles.FiT;
%fid=fopen(filename,'rt');
fprintf('Starting Webcam capture at %d:00, finishing at %d:00. \n Ctrl+C to break. \n \n ',StT,FiT)
TimedWebcam(StT,FiT);




function Commence_Callback(hObject, eventdata, handles)
% hObject    handle to Commence (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'String') returns contents of Commence as text
%        str2double(get(hObject,'String')) returns contents of Commence as a double
StT = str2double(get(hObject,'String'));
handles.StT=StT;
guidata(hObject,handles)

% --- Executes during object creation, after setting all properties.
function Commence_CreateFcn(hObject, eventdata, handles)
% hObject    handle to Commence (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white'),set(hObject,'string','9');
end
StT = str2double(get(hObject,'String'));
handles.StT=StT;
guidata(hObject,handles)



function Finalise_Callback(hObject, eventdata, handles)
% hObject    handle to Finalise (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'String') returns contents of Finalise as text
%        str2double(get(hObject,'String')) returns contents of Finalise as a double
FiT = str2double(get(hObject,'String'));
handles.FiT=FiT;
guidata(hObject,handles)

% --- Executes during object creation, after setting all properties.
function Finalise_CreateFcn(hObject, eventdata, handles)
% hObject    handle to Finalise (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    empty - handles not created until after all CreateFcns called

% Hint: edit controls usually have a white background on Windows.
%       See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor','white',set(hObject,'string','17'));
end
FiT = str2double(get(hObject,'String'));
handles.FiT=FiT;
guidata(hObject,handles)

Sunday, 12 January 2014

Not-so-spontaneous installing of OpenCV

Spontaneous Projects is a chronicle of all of my projects, a reference for me, and a way to prevent others from making the same mistakes. 

I think I've finally succeeded, it still needs some testing with other code, because I don't know how the integrated test programs function, but I think I managed it.

For the first section of this little saga check the older post here.

For the most part I followed these directions from murga-linux

Preparation


First, download and install Lucid Puppy (5.2.8 works)
Then, you need to download the devx file.

Then we need a few PET files, some of the ones in the linked post cause issues, with crashing xwin, or crashing the console somehow. On top of that they don't seem to be needed, it's possible that they are now rolled into the distro or the devx package.

DO NOT get new gtk+ files, they cause the xwin problem, and are not needed.

Download these from http://distro.ibiblio.org/puppylinux/pet_packages-4/
  • ffmpeg-20080731-i486.pet
  • ffmpeg_DEV-20080731-i486.pet
  • libjpeg-6b.pet
  • libpng-1.2.22-patched1-pup4.pet
  • libtiff-3.7.4.pet
  • fontconfig-2.6.0-prescott.pet
  • fontconfig_DEV-2.6.0-prescott.pet
  • x264-20080731-2245-i486.pet 
as well as

Now we add the devx sfs using SFS on-the-fly (Menu>Setup>Setup Puppy)

Back up your save file here, with wireless, a browser, the devx package and everything else needed for basic functionality.

Then install the PET's, just click run, or save and run them later. 

I reboot every now and then, because the xwin issues didn't manifest till the reboot, but given that I 
tracked them to xlib it shouldn't be an issue.

Installing


make the directory where you want OpenCV (</...OpenCV>)

#cd </...OpenCV>
#svn co http://opencvlibrary.svn.sourceforge.net/svnroot/opencvlibrary/trunk .

#cd </...OpenCV>trunk/opencv
#mkdir release
#cd release

#cmake -D CMAKE_BUILD_TYPE=RELEASE -D CMAKE_INSTALL_PREFIX=/usr/local -D BUILD_PYTHON_SUPPORT=ON ..

#make
#make install

#ldconfig -v
#export LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH
#cd </...OpenCV>/trunk/opencv
#export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig

These tests didn't run from terminal, I think they are actually in a different directory. You can find them manually though

#cd </...OpenCV>/opencv/trunk/release/bin
#./cxcoretest
#./cvtest -d </...OpenCV>/trunk/opencv/tests/cv/testdata/cv



I had no failures on the cxcore test, But the cv one had some, likely due to lack of inputs - it also had a segementation fault, so hopefully that isn't problematic.

Update: 13/1/14
I've compiled the samples, so it looks like it's all working as expected.
To run the samples, navigate to

</...OpenCV>/trunk/opencv/sample/c

and open a terminal. For LuPu you need to specify that you wish to use shell, so enter

sh build_all.sh

./edge
./motempl (if you have a webcam)
./ <any other program>
Use Esc to exit any of the samples

motempl in action, from what I can gather it identifies regions that have changed between frames

A little more movement in this one

And lots of movement as I move my hand and wave it about

Friday, 10 January 2014

Installing OpenCV (or trying to)

Spontaneous Projects is a chronicle of all of my projects, a reference for me, and a way to prevent others from making the same mistakes. 

I've spent the last few days trying to install openCV, an open source Computer Vision library.

It's not designed for Lucid Puppy, but there are posts about that indicate that it is possible. I've tried following the instructions for ubuntu on OpenCV's site, and got to 68% completion, but I was unable to find exact matches of some of the packages, and I think I may have forgotten to install dependecies on another - I thought it was an optional one, but maybe not.

I then tried the process shown at Murga-linux
As I was installing .pet files the computer siezed up a little, and seemed to stop installing them, on a reboot it appears that I have corrupted xwin. This isn't exactly surprising, given that I didn't remove the old packages, or make any effort to clean up.

So it looks like I'll be reinstalling LuPu and trying again using the Murga approach, but given that I was already planning on a fresh install soon it's not really an issue.

I was also able to copy my working directory from the SSD to a USB from the command line, so it appears that it's just xwin that is corrupt - I could probably try to fix it, but a reinstall will be easier.

Monday, 6 January 2014

Image Capture on linux

Spontaneous Projects is a chronicle of all of my projects, a reference for me, and a way to prevent others from making the same mistakes. 

For the first part of migrating to using the netbook as a computer vision device, I need to get an image from it.
I used a program called uvccapture as a basis, and modified it heavily, so that it runs in YUY mode all of the time, and has a lot less options, as I plan to use a modified version of this to capture for actual processing later.

The following was developed for a EeePC 701sd, running lucid puppy and compiled using g++ and a make file, the name is still the original, as I haven't fully got my head around how the makefiles work yet, so I kept it simple.
Lucid Puppy, (right) an older image showing both lack of centering and bad colours
(left) a recent pic, taken at the full res of the camera, in worse lighting, but with 1 second for the camera to adjust



#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <jpeglib.h>
#include <time.h>
#include <linux/videodev.h>

#include "v4l2uvc.h"

static const char version[] = VERSION;
int run = 1;

void
sigcatch (int sig)
{
  fprintf (stderr, "Exiting...\n");
  run = 0;
}

void
usage (void)
{
  fprintf (stderr, "uvccapture version %s\n", version);
  fprintf (stderr, "Usage is: uvccapture [options]\n");
  fprintf (stderr, "Options:\n");
  //fprintf (stderr, "-v\t\tVerbose\n");
  //fprintf (stderr, "-o<filename>\tOutput filename(default: snap.jpg)\n");
  //fprintf (stderr, "-d<device>\tV4L2 Device(default: /dev/video0)\n");
  //fprintf (stderr,
  //"-x<width>\tImage Width(must be supported by device)(>960 activates YUYV capture)\n");
  //fprintf (stderr,
  //"-y<height>\tImage Height(must be supported by device)(>720 activates YUYV capture)\n");
  //fprintf (stderr,
  //"-c<command>\tCommand to run after each image capture(executed as <command> <output_filename>)\n");
  //fprintf (stderr,
  //"-t<integer>\tTake continuous shots with <integer> seconds between them (0 for single shot)\n");
  //fprintf (stderr,
  //"-q<percentage>\tJPEG Quality Compression Level (activates YUYV capture)\n");
  //fprintf (stderr, "-r\t\tUse read instead of mmap for image capture\n");
  //fprintf (stderr,
  //"-w\t\tWait for capture command to finish before starting next capture\n");
  fprintf (stderr, "-m\t\tToggles capture mode to YUYV capture\n");
  //fprintf (stderr, "Camera Settings:\n");
  //fprintf (stderr, "-B<integer>\tBrightness\n");
  //fprintf (stderr, "-C<integer>\tContrast\n");
  //fprintf (stderr, "-S<integer>\tSaturation\n");
  //fprintf (stderr, "-G<integer>\tGain\n");
  exit (8);
}

int
spawn (char *argv[], int wait, int verbose)
{
  pid_t pid;
  int rv;

  switch (pid = fork ()) {
  case -1:
    return -1;
  case 0:
    // CHILD
    execvp (argv[0], argv);
    fprintf (stderr, "Error executing command '%s'\n", argv[0]);
    exit (1);
  default:
    // PARENT
    if (wait == 1)  
      waitpid (pid, &rv, 0);
 
    else {
      // Clean zombies
      waitpid (-1, &rv, WNOHANG);
      rv = 0;
    }
    break;
  }

  return rv;
}

int
compress_yuyv_to_jpeg (struct vdIn *vd, FILE * file, int quality)
{
  struct jpeg_compress_struct cinfo;
  struct jpeg_error_mgr jerr;
  JSAMPROW row_pointer[1];
  unsigned char *line_buffer, *yuyv;
  int z;
  sleep(1);
  line_buffer = calloc (vd->width * 3, 1);
  yuyv = vd->framebuffer;

  cinfo.err = jpeg_std_error (&jerr);
  jpeg_create_compress (&cinfo);
  jpeg_stdio_dest (&cinfo, file);

  cinfo.image_width = vd->width;
  cinfo.image_height = vd->height;
  cinfo.input_components = 3;
  cinfo.in_color_space = JCS_RGB;

  jpeg_set_defaults (&cinfo);
  jpeg_set_quality (&cinfo, quality, TRUE);

  jpeg_start_compress (&cinfo, TRUE);

  z = 0;
  while (cinfo.next_scanline < cinfo.image_height) {
    int x;
    unsigned char *ptr = line_buffer;

    for (x = 0; x < vd->width; x++) {
      int r, g, b;
      int y, u, v;

      if (!z)
y = yuyv[0] << 8;
      else
y = yuyv[2] << 8;
      u = yuyv[1] - 128;
      v = yuyv[3] - 128;

      r = (y + (359 * v)) >> 8;
      g = (y - (88 * u) - (183 * v)) >> 8;
      b = (y + (454 * u)) >> 8;

      *(ptr++) = (r > 255) ? 255 : ((r < 0) ? 0 : r);
      *(ptr++) = (g > 255) ? 255 : ((g < 0) ? 0 : g);
      *(ptr++) = (b > 255) ? 255 : ((b < 0) ? 0 : b);

      if (z++) {
z = 0;
yuyv += 4;
      }
    }

    row_pointer[0] = line_buffer;
    jpeg_write_scanlines (&cinfo, row_pointer, 1);
  }

  jpeg_finish_compress (&cinfo);
  jpeg_destroy_compress (&cinfo);

  free (line_buffer);

  return (0);
}

int
main (int argc, char *argv[])
{
  char *videodevice = "/dev/video0";
  char *outputfile = "new.jpg";

  //int format = V4L2_PIX_FMT_MJPEG; // OR
  int format = V4L2_PIX_FMT_YUYV;

  int grabmethod = 1;
  int width = 640;
  int height = 480;
  int brightness = 0, contrast = 0, saturation = 0;
  int delay = 0; // increased, may sort out the wrap issues, results in other issues, but fixes colours
  int quality = 95;
  time_t ref_time;
  struct vdIn *videoIn;
  FILE *file;

  (void) signal (SIGINT, sigcatch);
  (void) signal (SIGQUIT, sigcatch);
  (void) signal (SIGKILL, sigcatch);
  (void) signal (SIGTERM, sigcatch);
  (void) signal (SIGABRT, sigcatch);
  (void) signal (SIGTRAP, sigcatch);



  //Options Parsing (FIXME)
  while ((argc > 1) && (argv[1][0] == '-')) {
    switch (argv[1][1]) {

    case 'm':
       format = V4L2_PIX_FMT_YUYV;
      break;

    default: // this an unknown was entered case, nb -h is that
      fprintf (stderr, "Unknown option %s \n", argv[1]);
      format = V4L2_PIX_FMT_YUYV; // added here
      usage ();
    }
    ++argv;
    --argc;
  }


  videoIn = (struct vdIn *) calloc (1, sizeof (struct vdIn));
  if (init_videoIn
      (videoIn, (char *) videodevice, width, height, format, grabmethod) < 0)
    exit (1);

  //Reset all camera controls

  v4l2ResetControl (videoIn, V4L2_CID_BRIGHTNESS);
  v4l2ResetControl (videoIn, V4L2_CID_CONTRAST);
  v4l2ResetControl (videoIn, V4L2_CID_SATURATION);
  //v4l2ResetControl (videoIn, V4L2_CID_GAIN);

  //Setup Camera Parameters
  if (brightness != 0)
    v4l2SetControl (videoIn, V4L2_CID_BRIGHTNESS, brightness);

  if (contrast != 0)
      v4l2SetControl (videoIn, V4L2_CID_CONTRAST, contrast);

  if (saturation != 0)
     v4l2SetControl (videoIn, V4L2_CID_SATURATION, saturation);
 
  //if (gain != 0)    // It appears that gain does not exist, in this format, on this camera... who knows?
    //v4l2SetControl (videoIn, V4L2_CID_GAIN, gain);
 
 
  ref_time = time (NULL);

  while (run) {
 
    if (uvcGrab (videoIn) < 0) {
      fprintf (stderr, "Error grabbing\n");
      close_v4l2 (videoIn);
      free (videoIn);
      exit (1);
    }

    if ((difftime (time (NULL), ref_time) > delay) || delay == 0) {

      file = fopen (outputfile, "wb");
      if (file != NULL) {
switch (videoIn->formatIn) {
case V4L2_PIX_FMT_YUYV:
 compress_yuyv_to_jpeg (videoIn, file, quality);
 break;
default:
 fwrite (videoIn->tmpbuffer, videoIn->buf.bytesused + DHT_SIZE, 1,
 file);
 break;
}
fclose (file);
videoIn->getPict = 0;
      }
   
      ref_time = time (NULL);
    }
    if (delay == 0)
      break;
  }
  close_v4l2 (videoIn);
  free (videoIn);

  return 0;
}


Some Notes:

  • uvccapture uses some strange settings when initialising the camera, if there is not a delay to allow the camera to choose it's own settings it can be out of alignment, invert the colours, or be over/under saturated.
  • The gain function doesn't seem to exist for this setup, and throws an error 22 bug, once I commented out those lines it fixed itself. I'm not sure if it's hardware, software, or something else
  • There is likely still an amount of this that could be cut down, but until I know how I need the images to use them it will stay as it is. 


Early images, note the wrapping issue, and red appears blue

Recent image, with these issues corrected