maanantai 31. maaliskuuta 2014

Chili disaster

Completely off-topic but I have to vent a bit...

For some years now I have tried to grow some chili plants, but I seem to completely lack the famous "green thumb" as every attempt so far has failed miserably. Best so far was last year when I managed to grow a small plant but it didn't produce any fruit.

I haven't given up, though, and few weeks ago I planted some more chili seeds, among with some tomatoes and rucola (these because I happened to have some old seeds handy and few pots remaining after chilies) on small growing pots on window shelf. And amazingly they started to grow very nicely, almost every seed I planted. Maybe this is the year...

But no. Today I come home and our kid (almost 3 years old) has completely destroyed every single one of my plants. Every single plant ripped out from few remaining unspilled pots, all others empty on a pile of dirt on floor. So much for those plants. No point even trying to re-plant them, they're gone.

(no photos of the mess, although it would have made some ... disturbing material for people who prefer clean floors. Oh well, can't think of everything before cleaning up)

Oh the joys of parenting...

So, back to square one. Still had some tomato and salad seeds, among with some common chillies, but some other species I planted (Aji Benito and whatnot) were the last ones I had. So I had to order some more.

I have to mention Fatalii's site here, it's has been a good source of seeds and general chili growing information (nevermind my lack of success...). I really hope these new ones can grow in peace.

(punisment? two minutes on chair, as usual, with strict warning not to touch plants again. Kid wasn't alone, but wife was busy otherwise and thus failed to note the worst kind of warning sign there is - too long silence)

sunnuntai 30. maaliskuuta 2014

Phone screens and useless things

New phones are nice, but seem to be damn fragile, especially the glass screen. Some manufacturers' do demonstrate their sturdiness by dropping them, but of course they forget to mention that the way they drop them is very carefully planned and tested beforehand to minimize the risk of fracture.

Unfortunately in real life you don't do that planning before your phone drops, so risk of fracture exists. A case in point, my wife's Lumia that was dropped on tile floor (as you can see from on-screen date, this happened few weeks back, that's when the photos were taken, maybe I should write things up quicker sometimes...)


 Yes, it actually works, although the fracture makes it a bit hard to see the screen. And tiny glass shards also come off of it when using the touch screen, ouch.

Now, normally this wouldn't be worth of mentioning - get glass replaced (80€ at local shop) and that's it. What makes this a tiny bit more interesting is that I happened to have this on my desk:

This was mailed to be as a part of some advertising campaign a few weeks before phone broke. It is basically just a 5cm long stylus for using capacitive touch screen phones, with plug that fits in 3,5mm headphone jack for keeping it close to phone (the plug is kinda hard to see in photo). Just stylus, nothing else. I'm guessing you can buy these with your company logo for something like 50 cents each at 500 unit orders. So it's just cheap marketing crap. I don't even remember what the company was that sent that or what they advertised, but this thing was left laying [correct word? I always seem to mess that verb up] on my desk for some time as an example of Absolutely And Completely Useless Crap That Some Companies Think I Might Want --

-- Until it actually became useful, although only for a short while until screen got fixed. So not completely useless after all. I'll be damned.


sunnuntai 23. maaliskuuta 2014

Those Eureka!-moments

Funny. I have had an text about unexpected revelations (or "Eureka!" -moments) in my queue for a while now, but I wasn't exactly happy phrasing so it never got published. And now this reddit post (don't worry, it's "safe for work") caught my eye,in turn referring to another blog. So here it goes now, after some editing.

Writers have the (infamous) "writer's block". The same problem exists in software, although there is no similarly famous expression for it. "Coder's block", if you will. I'm pretty sure same applies for many other creative fields too, not just these.

You know the feeling. You have been working for a long time, doing whatever it is you do, but then some tiny part starts to fight back. The problem you encountered (whatever it is) should be trivial but yet you can't get it right.

For way too many people the solution appears to be to simply keep banging their head against the wall, hoping that the wall will give in first (well, proverbially). That is, keep working the problem and hoping to get through. As pointed out by numerous comments in above post (and original entry as well), many also have notice that it isn't really so.

In my opinion many of these comments are missing the point however. For some it is sitting in toilet, for some smoking, walking the dog (oh, I happen to fall in that category), or whatnot. But if you list one solution, I think it's wrong.

For me walking the dog works because it happens to be the time when my mind is "free". There's me, the leash, the dog and his interest in bush of the day. No thinking required from my part, well, at least for most of it. This is when the (as I call them) background processes of your mind take over. You don't have to be actively thinking the problem, it's already there in your head, and since your mind isn't otherwise (too) occupied, it can be worked on there, in background. And when that process finishes the solution pops in, like magic.

It's not what you do. It's what you don't do - think too much. Or better yet - just let your mind wander for some time a few times a day - be it walking, sitting in tiny room, smoking, cleaning or whatever. You might be pleasantly surprised on the results.


maanantai 17. maaliskuuta 2014

Motorcycle meter

Now briefly back to the electronics side. What happens when a device that is not weather-proof is installed to a relatively hostile environment? Text below has been published before, but I'm now adding it here again, with updates and small edits.


I've been asked a few times if the Eltrip-meters function on a motorcycle. The meters are primarily designed to be used in a location that is protected from rain and environment in general - that is, in a cabin of a car. Thus I've been forced to respond with absolute maybe.

Not very convincing, I know, so why wouldn't I try for myself.

I didn't have to look very far for a suitable target bike, as there happened to be a 2003-model Kawasaki ZR-7s in my own garage (shown on picture here, on August 2012, somewhere around Tyrnävä). I've owned this bike for total of seven years now, so before taking the bike out at the spring (this being in may 2012) I installed completely off-the-self, unmodified Eltrip-R20 meter to it. Absolutely no improvements, like adding conformal coating to electronics, waterproofing enclosure or anything was done; meter was exactly as taken from standard delivery packaging. 

As the bike's own speed/distance meter was mechanical, an external magnet-detecting sensor had to be installed. Since front tire had no readily suitable place for the sensor, I cut a suitable piece from a available piece of sheet metal and used it to attach the sensor between original sensor cable and brake holder. I glued two magnets on the brake disc holder with normal general utility glue; other of these can be seen on picture. The original magnets are still in place, so at least for this kind of driving the glue was sufficient. Real racing or off-road driving might require better attachment.

Meter itself was attached directly above the handlebar. I could have put the Eltrip above the bike's own meter, under the windshield where it would have been better protected, but since this was to test the meter in outside conditions I chose to install it on more exposed location.
The location above the handlebar is fairly far down from normal line of sight, so looking at the meter during driving requires taking eyes off the road for too long a time. Under the windshield would've been better for this too.
The actual installation was done with a few more pieces of metal attached under the bolts that hold the handlebar. Meter was also attached to these pieces of metal with screws. Attachment was sturdier than usual, but at least now random passing thief won't just grab the meter that easily. Again, on a location where there are more criminals around one might consider using velcro for meter so it can easily be taken with you when leaving the bike.
Meter power was taken after the ignition lock, so when bike wasn't driven the meter was unpowered. The bike has been outside for two summers now, directly exposed to the elements. The picture abovewas taken on june 2012, and by looking carefully some rust can be seen at the end screws of the meter. This so far is only sign of wear.

In same picture above at the left is PWM-based handlebar heating control unit I installed six years ago can be seen. The attachment for it is kinda MacGyvered together, and now I would do it differently. The electronics in heater control unit isn't protected either, and it's still functioning perfectly.
Meter has worked reliably for two summers now. Although there was a lot of rain, it never affected meter functionality at all, not even when starting up in heavy rain (driver's functionality in such conditions is another issue...). Since the meter was not constantly powered, the internal clock stops after a week or so, but that can be re-set easily enough.
Usage-wise even thin driving gloves make using of meter more difficult when driving. However, using the meter when actually moving is dangerous, so meter shouldn't be used when moving anyway; stop, then do whatever adjustments are needed before continuing driving.

After the first summer, when moving bike inside to hibernate over winter I removed the meter from bike to examine electronics in detail with microscope, but no problems or water-damage could be seen although there absolutely has been water inside the meter. In the end, the slight rust-coloring of the screws was actually only sign that meter had been in moist environment. After last summer I didn't even remove the meter - there had not been any reason to expect that anything had changed as meter still works perfectly. Now the third summer is creeping closer so the test continues.

And conclusions?

No large conclusions really can be drawn from this one simple test. Of course I can now, if asked, say that a meter has been on my bike for two summers and survived without a scratch. When installing a meter for an actual race it most likely would be located in a more protected place under the windshield and it might also be installed so that it can be taken off when not used, so it might not be that exposed to environment at all (or only briefly during race).
One might consider adding some hot-melt glue on the most exposed regions (seams at upper part of housing and display) to protect the meter further. Lower part of the meter should be left unsealed, as it's good to have a place where water (be it rain that somehow got in or condensation) can drain out from the meter.


Now, this absolutely has to be said: Although Eltrip did tolerate this test, this absolutely can not be generalized to all electronics! Eltrips have been designed to take some abuse in automotive use, so before starting this project I had pretty good expectation of the results already. Under no circumstances I recommend anyone to test this with their own devices unless they have been specifically designed or adapted for this kind of use. If you still decide to try, you will be doing this with your own responsibility.


lauantai 15. maaliskuuta 2014

Quick update on map project

Sorry folks, as it turns out I won't be talking about thread interaction in Qt anytime soo.

I was planning on having a background thread that handles most of the time-consuming operations - primarily of course the tile download. And what do you know, Qt actually offers such operations built-in asynchronously (in other words, the map screen won't just hang when encountering a previously unvisited tile; it just provides empty "please wait" placeholder until download is finished and real tile can be shown). And yes, background downloading is working now. That was actually almost too easy. (well, there was some minor issues, but after being exposed to QThreads, signals and slots, those were actually trivial) [I could rant about difficulties of multithreading, and how these are different when you are working on "low level" (C or C++) or "high level" (Qt over C++) systems -- drop a note if you want to read about my opinions on issue]

Well, at this point I can at least provide you some "screenshots". Well, it's full screen, and at the moment there are no floating controls. You may notice my "beautiful" (read: quickly drawn as test graphics) cursor at upper left corner.

Plans? Well, current location of course, shown as cursor. Route traveled (with distance) since start. Waypoints, or I'd use term "Points of Interest", with simple navigation ("that way towards waypoint", in cover of course). These are the things I use/could use the most personally, so naturally they have priority.

Possibly full route even (downloadable/e-mailable). And then. Well, I don't know, actually. For now I'll still be following the "scratch my own itch" route.



perjantai 14. maaliskuuta 2014

Drawing on Sailfish


Some time ago I got myself Jolla phone (which is based on Sailfish OS), and while I had some difficulties with it in beginning - the fully gesture-based UI takes a bit for getting used to - after latest system update ("Naamankajärvi") I've been really happy.

Well, except on application front, but that was to be expected. There aren't that many apps that are on my must-have list, but those two that that aren't available are very useful to me. These of course are Karttaselain and Sports tracker (Warning; their web site appears to be flash-based).

First one is very useful when in forest to keep you from wandering to a property where you shouldn't be, and latter is handy when, well, training, although I generally used only the distance measurement in that (which was really bad anyway, at worst showing 30% more distance than I actually had walked).

So, since these aren't available, I might as well try SailfishOS/Qt programming out and write simple combined app myself. As usual, primarily to scratch my own itch.

Sailfish encourages apps to be written in QML/Qt system. User interface is done with QML (with javascript based logic) and simple applications actually can be written entirely in it. I expected to be handling a lot of custom/downloaded graphics, so the natural choice was to write the UI in QML and backend in C++.

This however was when I started to run into trouble. Sailfish uses (rather new) Qt5, and while the Qt reference pages are very exhaustive (as in lots of minute detail on functions), they are really bad in describing overall basics (remember, I had never used Qt before). Also a lot of information in web is for older versions of Qt, and I constantly ran into forum posts and mailing lists that essentially said "you shouldn't do it that way" (and of course failing to tell what is the correct way) or "you can do that, but it's not supported" (again, failing to tell what is the correct way).

A frustrating week, indeed (granted, I was able to put only hour or two a day to this). I'll just paraphrase Edison: "I didn't fail at drawing graphics in dozens of ways, I found out dozens of ways that no longer work [in context of Sailfish]". If I were lesser programmer I just might have given up before getting anywhere.

So, to help someone else that might be in similar situation, I'll just post some basic drawing code here. I tried to remove all excess cruft so this only demonstrates how to integrate C++ drawing in QML UI in Sailfish.

This is based on default app provided with Sailfish SDK, so some adaptation is needed to make things fit together, but I'll expect any reader to handle that with ease. Also note that I have not tried compiling this at all, this is stripped down version of my current implementation so there may be some errors. I also haven't even tried this on real device yet, just in emulator, so all this may need to be taken with proverbial grain of salt.

And remember also that I am by no means Qt expert, I try to explain what is going on as well as I can, but there may be errors here.

Let's start with C++ header, "graph.h". The main view in this case is "GraphView", which is derived from QQuickPaintedItem.

Method paint is where the magic happens. This is called by framework whenever contents of item should be repainted. More of it below.

Q_INVOKABLEs are functions that can be called from QML code; in this case they are used to grab mouse (sorry, finger) movement so view can be scrolled.
class GraphView : public QQuickPaintedItem
{
    Q_OBJECT

public:
    GraphView(QQuickItem *parent = 0);
    ~GraphView();

public:
    void paint(QPainter *painter);

    Q_INVOKABLE void onPress(int x, int y);
    Q_INVOKABLE void onMove(int xd, int yd);
    Q_INVOKABLE void onRelease(int x, int y);

private:
    bool moving;
    QImage *testpic;
    int xpos,ypos;
    int moveLastX,moveLastY;
};

Then the QML of this view, "graphpage.qml" (this should be referred from "main.qml" as initial view). Note CustomComponents declaration; this is needed for our C++ -defined view, which is defined as "GraphView". MouseArea is used to grab and pass touch notifications to the C++ code; the implementation simply passes the event to Q_INVOKABLEs defined in C++ code.

import QtQuick 2.0
import Sailfish.Silica 1.0
import CustomComponents 1.0

Page {
    id: graphpage

    GraphView {
        id: graphview
        objectName: "graphview"
        anchors {
            top: parent.top
            left: parent.left
            right: parent.right
            bottom: parent.bottom
        }

        MouseArea {
            anchors.fill: parent
            onClicked: {
            }

            onPressed: {
                graphview.onPress(mouse.x, mouse.y)
            }

            onReleased: {
                graphview.onRelease(mouse.x, mouse.y)
            }

            onPositionChanged: {
                graphView.onMove(mouse.x, mouse.y)
            }
        }
    }
}

Then the C++ itself. Note again that the standard headers/includes are not included in code below. More information on C++ function comments.
#include "graph.h"


/* ----------------------------------------------------
 * Default constructor.
 * We also create a new QImage that is drawn on screen; this is
 *
expected to be small 32x32 PNG that is defined in resources.
 * Note that if image does not exist in resources, this does NOT throw
 *
but silently creates an empty (invisible) image.
 */
GraphView::GraphView(QQuickItem *parent)  :
        QQuickPaintedItem(parent),
        moving(false),
        xpos(100),
        ypos(100)
{
    testpic = new QImage(":/test.png");
}


/* ------------------------------------------------
 * Remember to always clean up after yourself!
 */
GraphView::~GraphView()
{
    if (testpic)
        delete testpic;
}



/* ------------------------------------------------
 * This is the main drawing function that is called by framework
 *
whenever updating is needed. Do not call this yourself.
 *
 * As example we have just a small image that can be moved around
 * with touch.
 *
 */
void GraphView::paint(QPainter *painter)
{
    QRectF r(xpos,ypos,32,32);
    painter->drawImage(r, *testpic);
}



/* -------------------------------------------------
 * This is called when touch is detected. Mark that we are moving
 * (although it shouldn't be necessary in touch-based UI; we should
 * get move-events only when pressed anyway) and start coordinates.
 */
void GraphView::onPress(int x, int y)
{
    moving = true;
    moveLastX = x;
    moveLastY = y;
}


/* ----------------------------------------------------
 * Touch/mouse moved. If pressed, calculate new position and
 * signal framework that this should be redrawn.
 */
void GraphView::onMove(int x, int y)
{
    if (moving) {
        int dx = x-moveLastX;
        int dy = y-moveLastY;


        if (dx && dy) {
            xpos += dx;
            ypos += dy;

            moveLastX = x;
            moveLastY = y;
           
             // I am not exactly sure that this is the most correct way
             //
to do this, but it appears to work.
            setFlag(QQuickItem::ItemHasContents);
            update();
        }

    }
}


/* --------------------------------------------------------
 * Touch released; send final move event (it should have been
 * handled already anyway, but just in case) and remove "moving" flag.
 */
void GraphView::onRelease(int x, int y)
{
    onMove(x,y);
    moving = false;
}




/* ---------------------------------------------------------
 * The main.
 */
int main(int argc, char *argv[])
{
    QGuiApplication* app(SailfishApp::application(argc, argv));

     // Register our custom view in CustomComponents package, version
     //
1.0, so it is available in QML.
    qmlRegisterType<GraphView>("CustomComponents", 1, 0,"GraphView");

     // Usual initialisation.
    QQuickView* view = SailfishApp::createView();
    view->setSource(SailfishApp::pathTo("qml/main.qml"));
    view->show();

    return app->exec();

}
So there. Hope this helps :)

Oh, and of the my own map/tracker app - it's work in progress, I may or may not release it at some point. If there is interest, drop me a note, I'll keep updating this page. The main issue is the gigabytes of map data that needs to be hosted somewhere - and hosting isn't exactly free, unfortunately.

Don't expect anything too quickly however - right now I'm trying to figure out how to work with QThreads (to make downloading pages that aren't yet locally available a background operation). I expect it to take a good calendar week (again, hour or two a day) to get it working based on quick glance I took yesterday.