perjantai 25. huhtikuuta 2014

Tiny PICs: Schematic and software


This took I little longer than I intended, but after a few distractions here is the last chapter (for now at least) for using PIC12 for toy modification. So now the electrical and software details.

The airplane used three LR44 1,5v batteries in series, so it fit perfectly for PICs operating voltage limits of 2-5v. The white LED had forward voltage drop of 3v, and original series resistor was 120 ohms, meaning about 8 mA for forward current. Easy enough to handle.

I used PIC12F509 for this. PIC10F206 would have been sufficient too, but for some reason I just couldn't get it working, so after a few hours I just gave up. I could load software on the chip but it wouldn't do anything. Weird. Most likely just some stupidly minor detail I missed, but I just couldn't justify using more time on that now, especially since PIC12 worked right away. Since I only that two PIC12s remaining and five PIC10s from last attempt, I suspect that last time I tried situation was the same (yes, tried multiple PIC10s, same result with all, must be the software, or build environment bug)

So I decided to use original LED and series resistor as-is. Single pin of PIC can source 25mA (IIRC), but I still connected two in parallel (specifically GP1 and GP2, pins 5 and 6) to source the LEDs. No reason really, but the "feel good" factor for ridiculously over-engineering single part of design.

My paper schematics end always looking the same, some parts huge and some parts tiny. Oh well, guess I'll just explain it then since schematic isn't exactly most readable.

Circled + and - symbols are battery positive and negative; connecting to PIC pins 1 and 8 respectively. It may not be necessary but I still added small bypass capacitor directly between power pins. For some applications you may get away without one, but as rule of a thumb you'll always want to put one there, especially when there are significant current changed around (like here, 100nA to 10mA) as they smooth out voltage seem by MCU.

Button is connected between pins 8 (GND) and 7 (GP0). GP0 is also very very weakly (1Mohm) pulled high. Since there is basically no load on this pin the pull-up could be a lot smaller without affecting standby power consumption (say, 10k). For EMI resilience (for very very noisy environment) you might want to use smaller resistor (or more importantly, actual well designed PCB). And finally the LED with series resistor. All in all, very simple build.

I also mentioned that it might have been possible to use original switch instead of button. This assumes that the three-pin switch is breaking type (that is, connection is broken before other side is connected). In such case center pin would be negative, and both sides are connected to same sense pin and common pull-up. Pull-up might need to be smaller in that case to pull line up during short break period but it would also make constant always-on current draw so you still would want to use as large resistor as you can get away with.

Now, the software. When dealing with MCUs without OS I just write all the software in plain C nowadays, even for tiny devices such as this. I see no point in learning assembly of even one device crossing my path, there are just too many different MCUs I use. There are exceptions, of course, but there must be sufficient financial reason to spend time delving into mysteries of specific assembly dialect for me to bother for anything more complex than often-useful NOP and almost-always-necessary interrupt enable/disable instructions (and really, nowadays compilers almost always have macros for those - and more)

For PICs I do majority of my work in MPLab X, and for C compiler I used MicroChip's XC8 compiler. Software was fairly simple; whenever processor is reset (for any reason, but typically power-on or wakeup due GP0) it will turn LED on, wait for approximately 5 minutes (timing isn't that critical so variance in RC oscillator is not an issue) and then drop output drivers and enter back to sleep.

#include <xc.h>

// CONFIG - PIC12F509 Configuration Bit Settings
#pragma config OSC = IntRC      // Oscillator Selection bits (internal RC oscillator)
#pragma config WDT = OFF        // Watchdog Timer Enable bit (WDT disabled)
#pragma config CP = OFF         // Code Protection bit (Code protection off)
#pragma config MCLRE = ON       // GP3/MCLR Pin Function Select bit (GP3/MCLR pin function is MCLR)


/* -----------------------------------------------------------
 * Small delay. About 3ms (as measured)
 */
void delay()
{
  unsigned char i;
  for (i = 0; i < 250; ++i)
    { asm ("nop; nop; nop; nop; nop; nop; nop; nop; nop; 
            nop; nop; nop; nop; nop; nop; nop; nop; nop; nop");
    }
}


/* --------------------------------------------------------------
 * Simple main. On startup LED will be on; after specified time
 * it is turned off, and processor will enter sleep mode.
 */
int main(int argc, char** argv)
{
  unsigned int counter;

   // Configure IO:
   //   GP0      = input (externally pulled high, button pulls down to wake)
   //   GP1, GP2 = LED output (drives high)
  TRISGPIO = 0xF9;
  GPIO = 6; // LED on after wakeup

   // Enable wakeup on pin change (GP0,1,3); disable pull-ups;
  OPTION = 0x40; // 0100'0000

  counter = 0; // timer counter

  while (1) 
    { ++counter;
      if (counter == 33333) // 9 ms per iteration; this makes about 5 minutes
        { GPIO = 0; // turn LED off

          delay(); // let drivers settle (this may not be necessary)

          GPIO; // dummy read state before sleep (required for proper function). 
          GPIO;
          asm("sleep");

           // pin 0 change will then reset chip, (re)starting main again.
          
        }
      delay();
      delay();
      delay(); // 9ms total per iteration
    }
}

This absolutely isn't something I'd put into production, as I don't feel that it is as resilient to external interference (EMI) as it could be (or even optimal solution to this problem actually). My hunch is that this may react "badly" to RF interference (not in sense that it'll cause fire or anything, more like waking up when not needed) but in this case it is not that big problem.

But for intended purpose - to make a toy last a bit longer as useful - it is good enough. That for now, that is more than enough - already forgotten (dead) toy became "hot" item again. Weird how doing something "useless" like this gives you that nice, warm feeling inside...


keskiviikko 23. huhtikuuta 2014

SailfishOS: Accessing GPS

I suspect there are many others that have wanted to use GPS on their Jolla phone application but have not been successful in their attempts. In that case this should help you a bit.

If you are in hurry, just skip to the end, DBus code is there in all its ugliness. Everything in between is mostly background.

At the moment SailfishOS' Qt is something between versions 5.1 and 5.2. For GPS (or more accurately, the positioning information in general) this is unfortunate as old QtLocation subsystem no longer exists and new QtPositioning isn't there yet. After numerous web seaches I came in conclusion that following options are available right now:
  • Older QtLocation (possibly with custom import module). Reading between the lines I got the impression that if you wish to publish your app on Jolla's official shop this is very much frowned upon there.
  • Import custom module based on QtPositioning and use it. Slightly better, but this may later bite you back when phone is updated and official (yet possibly slightly different, as API is not yet completely stable) system interferes with your custom solution. So this also is frowned upon.
  • Hack to the DBUS and obtain location from there. Also frowned upon, but apparently least of these options. Of course no one bothered to mention how to do it...
Well, I went for the last option anyway, planning to upgrade to QtPositioning when it becomes properly available. It's way easier anyway than all this DBus mess.

Now, if you have read what I have written about my experience on working on Qt (previously zilch but at least I had browsed quickly some docs in the past), QML (maybe I had heard of it somewhere, not sure) or DBus (at least I had heard of it) you may already have guess how easy my progress to the depths of DBus was.

Well, actually, it wasn't as bad as I first expected, browsing the lower level documentation. As I had map drawing system running already, so I was getting familiar with "the Qt way". And since Qt appears to have everything and kitchen sink included (for the better or the worse, depending on your view), I figured there might be DBus too... And what do you know, there is.

Now, with that hurdle passed, proceed to the next. SailfishOS uses actually older implementation of Geoclue, references found here. The older version is very badly documented and examples are just about eually good - unfortunately even those are using C API (not available here, at least without more custom modules) that doesn't translate direcly to Qt/DBus combination. And Qt's DBus subsystem is very picky about defining call signatures (damn you Geoclue for using almost completely unnecessary structs to pass data I don't even care about - but Qt does, just enough to not to co-operate with my efforts). So good luck there, especially since Qt documentation mentions structs, arrays and dictionaries in passing - but completely neglects to mention how they should be used.

Did I remember to  tell you how frustrating some things were?

Even Google isn't very helpful when trying to find something this obscure. But eventually, after hundreds of searches (no, I am not kidding there) with varying search terms I managed to scrape together enough information to write my own code. Other search providers were even less helpful.

Eventually I scraped together enough information to work on. So, I implemented everything according to Geoclue and... nothing. No position information. Based on all the examples I had I should have updates coming, but no. Que debugging information, and when trying to send "GetPosition" I get result in tune of "Can't be done as there are no location providers" (I don't remember the exact phrase used). Wut? But this Maps app here has position coming in... Lightbulb moment...

At this point I had managed to gain enough knowledge of DBus in general and Qt's abilities so I could started to get creative. On terminal you can use dbus-monitor to, well, monitor what's going on dbus. So I started logging everything (if you want to do this too, log in file - there will be lots of events across all subsystems), started Maps app, and then quit soon after starting and started reading the logs.

And what do you know, the Maps app actually doesn't seem to use the Geoclue.Position interface; it accesses directly the Hybris (that's the GPS - and GPS only - provider) for location information (the interface for that is org.freedesktop.Geoclue.Providers.Hybris - so far I haven't found any relevant interface documentation about it or even Providers in general). So insert a short (and very very boring) montage of software hacking in all its glory here and soon the GPS position updates started coming in. Whew!

So, now for the actual implementation. As my project is in C++ (except the UI), the GPS interface is too. It shouldn't be too difficult to build quick adapter to access this from QML either, but I won't go to details of that here.

So, first your project. To use DBus you must have line
QT += dbus
In your .pro file.

It is best to implement your receiver as a separate class that provides its own interface for rest of your app, making it easy to switch to QtPositioning later when it becomes available. So the header (vastly simplified, relevant includes are left as exercise for the reader, that shouldn't be too difficult)

class PositionSource : public QObject {
    Q_OBJECT
public:
    PositionSource(QObject *parent);
public slots:
    void positionChangedDBUS(QDBusMessage);
private:
    QDBusInterface *masterInterface, *clientInterface, *hybrisInterface, *hereInterface;
};

And Cpp (again, I'm skipping everything but the most interesting parts). Also the Blogger's editor doesn't seem to like <> tags, so it may have messed something up during edits.

PositionSource::PositionSource(QObject *parent) :
    QObject(parent)
{
    masterInterface = new QDBusInterface("org.freedesktop.Geoclue.Master",
                                         "/org/freedesktop/Geoclue/Master",
                                         "",
                                         QDBusConnection::sessionBus() );
    QDBusReply<qdbusobjectpath> createReply = masterInterface->call("Create");
    qDebug() << "create:" << createReply.value().path();

    if (createReply.value().path().length() < 5) { // just quick-and-dirty check 
        qDebug() << "Could not create geoclue client";
        return;
    }

    clientInterface = new QDBusInterface( "org.freedesktop.Geoclue.Master",
                                          createReply.value().path(),
                                          "",
                                          QDBusConnection::sessionBus() );

    QDBusMessage msg;

     // GeoClue has "SetRequirements" function where you can specify your
     // app's requirements. Note that if they are too strict (like you
     // ask for precision no position provider can do), GeoClue doesn't
     // seem to fall back to "lesser" provider but will fail to give you
     // position information at all.
     // I am not sure if that was reason for original problems with
     // Geoclue.Position interface (found out about that only later, by
     // reading actual geoclue sources) but proceed with caution if you
     // want to try that.

     // SetRequirements: 
     //   accuracy level: GeoclueAccuracyLevel-enum
     //   minimum update time
     //   require updates
     //   resources, another enum again; (1<<2) should be GPS, (1<<10)-1 "anyting"

    clientinterface->call("SetRequirements", 1,0, true, 1023);


     // This most likely isn't very relevant when using Hybris directly, but I kept it anyway.
    clientInterface->call("PositionStart");


    // Then, register Hybris provider.
    hybrisInterface = new QDBusInterface("org.freedesktop.Geoclue.Providers.Hybris",
                                        "/org/freedesktop/Geoclue/Providers/Hybris",
                                        "",
                                        QDBusConnection::sessionBus() );


    msg = hybrisInterface->call("AddReference");
    if (msg.type() != QDBusMessage::ReplyMessage) { // quick and dirty check
        qDebug() << "Couldn't access Hybris : " << msg;
        status = POS_UNKNOWN;
        return;
    }

    // SetOptions parameter appears to be: (I'm guessing this implies auto-detect)
    // I have no idea on how to actually create the providerOpts so Qt would accept it
    // (and Qt documentation is *wonderfully* vague about that), but I'm leaving this
    // here in case someone has good ideas)
    // This call doesn't seem to be necessary anyway since position is obtained anyway,
    // but on different hardware this might have different results.
    //   array [
    //      dict: "gps-baudrate", 0;
    //      dict: "gps-device",   "";
    //   ]

    /*
    msg = hybrisInterface->call("SetOptions", providerOpts);
    if (msg.type() != QDBusMessage::ReplyMessage) {
        qDebug() << "Couldn't set hybris options : " << msg;
    }
    */

     // These are just for general information
    msg = hybrisInterface->call("GetProviderInfo");
    qDebug() << "  Hybris provider info: " << msg;

    msg = hybrisInterface->call("GetStatus");
    qDebug() << "  Hybris status: " << msg;

     // Now, if you really wanted to, you could do same for org.freedesktop.Geoclue.Providers.Here,
     // to get information from it. But then again, why bother? (especially if you are concerned about
     // privacy).

     // Then connect the PositionChanged signal. I'm connecting also the Geoclue.Position, but
     // so far it has never been triggered.
     // Note that after cold-start it may take a long while before you start getting position fix,
     // especially if you are indoors.
    QDBusConnection::sessionBus().connect("org.freedesktop.Geoclue.Position",
                                          "/org/freedesktop/Geoclue/Position",
                                          "",
                                          "PositionChanged", this, SLOT(positionChangedDBUS(QDBusMessage))); 
    QDBusConnection::sessionBus().connect("org.freedesktop.Geoclue.Providers.Hybris",
                                          "/org/freedesktop/Geoclue/Providers/Hybris",
                                          "",
                                          "PositionChanged", this, SLOT(positionChangedDBUS(QDBusMessage)));
}

// The message slot. This only spits out the data, parsing is up to you.
void PositionSource::positionChangedDBUS(QDBusMessage msg)
{
     // expecing int,int,double,double,double - flags (which data is valid), time, lat, lon, altitude

    QList<QVariant> list = msg.arguments();

    qDebug() << "PositionChanged:" << msg;
}

If you monitor the Geoclue.Position interface, there seem to be messages being sent but they certainly aren't being received by this code. No idea why.

Also note that you should also call RemoveReference for Providers (and possibly for client) when you're done (so in your adapter destructor). Unfortunately there is no way to explicitly tell GeoClue (as in client or provider) that you're done and it should shut down (at least no documented way on DBus interfaces) - RemoveReference only tells it that it may shut down if it pleases it to do so. On phone it appears that even after asking interface to close the GPS stays active even when no one is using it, eating battery. Kinda stupid interface design if you ask me. 

The code above should be runnable on the phone, but may not be in emulator (I didn't actually try, oh well). Since this is untested copy-paste from my code there may be some errors, sorry about those in advance.

Now, looking back at that mess I can make an educated guess why Jolla folks haven't been exactly forthcoming with this information, as this pretty much is accessing very very unofficial and possibly undocumented subsystems for location information. In this context this means that it may vanish without warning, but until QtPositioning rolls in, I unfortunately don't really see another (good) way to do this.

Update:
It seems that you can actually skip GeoClue master/clients completely (everything up to (down to?) "PositionStart" call in above code) and only create/connect to HybrisInterface. This seems to make position information lock slower (may take several minutes, up from 20 seconds or so I experience earlier while inside), but then RemoveReference on shutdown will actually stop GPS (well, make the icon go away at least) and hopefully also stop excessive battery drain after shutdown.
 

tiistai 22. huhtikuuta 2014

Software guy in FPGA land

I have to admit it, I am primarily a software guy, have always been. I can take a random chip, look through its datasheet, build connecting electronics around it and make it dance with software (with some assistance from suitable MCU of course). But if you reverse the situation - that is, if I need to make a hardware module to do the dancing (in this context I mean FPGA) I'm lost. I am familiar enough with basics, but to actually implement something relatively simple (say, a simple controller that can take data from outside, store it in internal memory and run a sequence based on data) I seem to be facing a very steep cliff.

For example this little thing. Pen for scale; actual board size is 60x60mm (JTAG wires you can see behind the board go to small helper board I put in there to make development a bit easier).














I've had this sitting on my desk for almost a year now (mostly because the projects that actually do pay the bills have been a priority). This is an 8x8 RGB led matrix. What I hope makes it interesting is the fact that it is self-controlled, chainable (you can in theory chain dozens if not hundreds of these together in any shape you want, based on your current need) and it is trivially controllable by even tiniest of the MCUs (say, the PIC12 I wrote about earlier - with a little help from a shift register to extend output pin count, but an Arduino with simple adapter shield should do nicely).

The idea is that you "pre-load" data in by clocking RGB data (each component separately, with up to 10 bits in parallel for each; so loading first to LEDs is R10 - dataclock - G10 - dataclock - B10 - dclock - R10 - dclock - G10 ... and so on). Timing requirements are not strict so you can take your time calculating next value between data clocks. When you have your entire matrix loaded with data (that is, every LED in every module you have in chain), you can signal them all to switch data to new with "flip" signal pulse. So essentially you can load an image to them, flip, load new image (and you can take all the time you want), and flip again - no jitter, just instant image change. Very very simple. (some details omitted, they aren't that important right now)

This takes in 5v input (though I already found out that it can tolerate 12v, for short periods at least, it just gets really hot - that should teach me to use same power source for different projects and then forget to change) and with every LED at maximum brightness (white) single module uses about 1,5A. Typical use of course would be less, directly proportional to overall brightness.

Now, as you might have guessed, "the dance" here is ability to drive all the LEDs, load new data in background and then load new current scaler values when needed. Since I had some spare time now, I started with VHDL again (it was a long time in between, so even basics needed a quick refresh), and actually have made some progress. That is to say, it won't work. Something fishy when trying to access internal RAM. The fetch process itself appears to be running nicely, just the bits in RAM refuse to come out.

But at least it seems that during the period of inactivity the background processes in my head haven't been idle - when last working with it I was completely stumped on how to build process to access the RAM, now it seemed to be crystal clear from start.

Except that "doesn't work" part. But I'm working on it.

perjantai 18. huhtikuuta 2014

Tiny PICs: Toy modding

Over last few entries I've written about small PICs, now for the actual implementation. And it's a toy!
We got this book based on certain animation (that shall be remain unnamed, as well as the creator) some time ago and it had this airplane-shaped "projector" with it. When turned on, it could project a picture (you could change the shown picture, one out of about dozen, by pressing button).
Our son loves it, or mostly the light in it. And of course he quickly figured out that tiny switch in bottom turns the light on (and off? never!), so usually he went to sleep holding it, light on, and batteries (3 LR44s) didn't last a week.


No way I'll keep buying more batteries to just have them last a week, so maybe some light modding, say, some electronics in it to turn it off automatically after five minutes or so. I first thought implementing the light with a PFET and analog timer (mainly because I hadn't used those before, unlike MCUs that I considered too easy), but it seems that no suitable simple timer chips exist (or more likely I just couldn't find one).

So, a PIC then. Some quick back-of-the-envelope calculations indicated that by using the sleep mode of these small PICs (approx. 100nA consumption) with wakeup functionality tied to a button, batteries with approx. 100mAh capacity would last approximately "long enough so it's forgotten already". I first thought of using external PFET to turn everything off (including MCU, to be woken up with touch of button) when not needed but the additional energy savings here would be so minimal that I discarded that idea for now.

To determine what would be needed I of course needed to first silently steal it (with empty batteries it held almost no interest to the small one so this was easy) and then take it apart (four standard screws, one of which held battery compartment closed, easy too. Tail was very tightly fit together so it took some careful application of force to not break anything).

So, first impressions. The design is actually pretty well-thought for a simple toy. Two halves have protrusions that hold all the internal pieces in their designated positions with no screws or other fasteners. LED part was pretty much as expected; LED (with 3v forward voltage), 120ohm resistor and simple switch. Button at bottom pushed rod up to rotate wheel with the small pictures in it, and two lenses to focus the image (one fixed and one in propeller "tube" to focus by moving it. If you try this yourself, note that the fixed lens is asymmetrical - if you put it in wrong you won't get any good picture)

All things taken apart. Starting from upper left corner and proceeding right then down; button/push rod to change picture (missing the spring that goes with it); top piece, battery compartment cover, propeller/lens piece, picture wheel and (plastic) lens next to it, some tools, bottom part, led/switch assembly with resistor. Both LED and switch are held in place by LED and resistor wires that are soldered to battery compartment leads in on bottom part of plane. Curiously the solder on battery leads looked a bit too shiny for standard RoHS-compliant stuff but I didn't bother to examine it further.

Closeup of the picture disc. The entire disc is about two centimetres across, so individual images are about 5mm across. It could produce image of approx 10cm across with relatively good detail , so print detail on that slide must be pretty fine. I wouldn't be surprised if that printed slide were the most expensive part of the entire plane with that amount of detail (but then again, I am not that intimately familiar with capabilities of current printing processes so I might be wrong). Counting here is seems to have 10 images total (instead of dozen I guesstimated above), my mistake.

On picture below you can see the modified led/switch holder of right. The original switch has been taken out and replaced with (slightly larger) push button I had available. Due to this the hole at the bottom of the plane had to be enlarged too. The I/O line that is monitors the button is pulled high with 1M resistor. Only later I realized that since the original switch had three poles so I might have been able to use it directly without bothering with the button. Oh well.
The original 120ohm resistor is connected directly to two PIC outputs (the current through LED is only 8 mA with full batteries so just one output would be sufficient, but I still used two). Small bypass capacitor can also be seen here. The MCU is placed on holder for easier testing/reprogramming (take it out from holder and put to programming header - for a proper product I'd put programming pins on tiny surface mount PCB with LED and switch on it, or for really large volumes order pre-programmed chips. Funnily enough I'd estimate that tiny PCB with all electronics on it (plus two wires for battery) might actually be cheaper than current construction where everything has to be hand-cut and soldered, but then again, that might be wrong as I have no idea of the said priced in china.
Unconnected wires are battery positive and negative.

From the other side.

After testing this on desk it was time to put it all together. Here the button/led assembly is in place, battery wires not yet attached. I also added some hot-melt glue the MCU to protect it from mechanical strain (it gets thrown around a lot). LED placement has to be just right for proper light output, so care has to be taken, especially if you change the button.

From front. Note the spring on picture changing pole at front. Spring is not the original one, that one  fell from the table and crawled to some hiding place I have yet to find so I had to salvage some non-functional promotional pen for new one. Note also the changed battery wire; those red wires are thin, single-strand wires, nice for PCB repair where they do not move after placing as they break very easily. In this kind of setup you do not want to use them, as I painfully learned after having to re-solder/replace them a few times. The only reason I used them in the first place was that they were light and I had roll of it available, so lesson learned here.
The MCU blob was a bit tight fit but I managed to push it in cockpit part with two-sided tape. Eventually.

All done and it works! Whee!


Next; more details on schematic and software used.


keskiviikko 16. huhtikuuta 2014

Tiny PICs: Neat little chips

As previously said, I had handful of PIC10F206 and PIC12F509 remaining from an old project. Dates on the chips indicate that they were manufactured late 2004 and mid 2005, so I'm guessing I bought them late 2005.

These chips really are fascinating, albeit in perverse sort of way if you are more used to bigger chips commonly available today. They come in 6-pin (surface mount) or 8-pin (DIP) packages, with up to 6 GPIO lines available, depending on chip and configuration. Not much memory either; smallest of them (PIC10F200) has whopping 256 word flash (do read that again: 256 words. Don't let the "word" confuse you; PIC uses 12-bit instructions and one such instruction is referred as "instruction word", so in essence that flash has room for 256 assembly instructions) and 16 bytes (bytes!) of SRAM.

Operating voltage can be anything between 2.0 and 5.5v and they use about 350μA when running on internal RC oscillator at full 4 MHz speed (that at 5v, less at smaller voltages). At sleep they use less than 100nA. These figures are pretty impressive. Yes, nothing spectacular by today's standards compared to say MSP430 or Energy Micro products, but remember, these are 10-year old chips that cost about 1€ apiece at your local electronics store and some cents in volumes.

Then the serious drawbacks; no interrupts. Yes, you read that right, no interrupts at all. The closest thing is that they can wake from sleep (that's the 100nA mode) when activity is detected on some pins or watchdog expires. The gotcha is however that "wakeup" doesn't resume operation from the last execution point but instead does full chip reset, including resetting the GPIO's tristate buffers to default mode (all I/Os input - not fun if you want to hold some output line for longer periods). At least you can programmatically determine whether reset was due to change in I/O, power-on reset or watchdog and proceed accordingly, but there still will be a short output drop during reset.

Now, considering that there are no interrupts, the fact that they do have a timer module (some of them at least) is a bit perplexing. What can you do with a timer that can't generate interrupts? Especially since it can't be used to wake processor from sleep either. But then again, it appears to be capable of counting external pulses (with optional divider), so it might be one use for it (you can access its internal counter directly, although brief glance over datasheet seems to imply that timer module is disabled during sleep making that less useful feature).

All this makes writing software for them somewhat difficult, especially if you are used in working with more usual MCUs. I admit, it took me a while to get used in thinking really small.

All this being said, don't get me wrong, I absolutely do not recommend these chips as primary MCU for miscellaneous projects, these are absolutely not suited that. For general purpose MCU pick a suitable suitable AVR (Arduino) or some equivalent PIC18 instead. But if you have very specific need for small device these may be worth the trouble.

Now, look at those voltage and current figures again.Wouldn't this thing be just perfect for a battery-operated widget that only has to wake up every now and then to do briefly something and then return to low-power mode? Yep, more about that next time. For now I'll just leave you with a small teaser:













What could it be?

 

sunnuntai 13. huhtikuuta 2014

Quick update on "maps/tracker"





I've been working with Jolla (Sailfish OS) "sports tracker" / topographical map software on my spare time (which I unfortunately have very little, generally on late evenings when I'm already spent), and now I start to be quite happy with the map functionality. Maps can be browsed and loaded on-demand from the server, either simple topographical map with various scales (at the moment 1:10k, 1:20k, 1:40k and large-scale overview) and various data (topographical, aerial image, optionally with property borders and numbers).

Basic GPS route calculation support exists too, but apparently at the moment access to GPS requires either using "unofficial" QT APIs or digging into DBUS. I'm not very happy with first one, so until QtPositioning becomes officially available, DBUS it will be. Next I'll start trying to dig into it, but I don't expect fast progress since DBUS is completely foreign beast to me and there aren't examples of it for Sailfish available. It may take a few days (read: calendar weeks).

Some examples (yes, everything in Finnish, since only Finnish map data is available). The purple line in middle is (simulated) GPS track. I know, it doesn't show too well, either by shape or color. I'll try to work out better indication.

By pressing-and-holding on somewhere on map you open context menu. The location is also highlighted as "Point of Interest" (grey marker). You can store that location ("Lisää huomiopiste"), navigate to stored points ("Valitse huomiopiste"), delete one (if you opened menu on one), change map type ("Kartta-aineisto") or start tracking new route ("Aloite reitti"). Last item is "reload", primarily for debug purposes.



Now, the bad news. Maanmittauslaitos (National Land Survey Office of Finland) provides topographical data for free. However, since software has also access to non-free data (property borders and identification) I have to pay for data access to MML. (and unfortunately free data does not mix very well with non-free data, due to very different implementations). So I can't just give this software away. Sorry. But if you are interested let me know, we may be able to work something out.


torstai 10. huhtikuuta 2014

Adapter for tiny PICs

With Arduinos it seems that Atmel's AVRs are getting all the glory today. Personally I like Microchip's PICs more - but that is just because I have been using them for a long time and I am familiar with them and tools involved. Technically both chip families are pretty much equivalent so there is no reason to prefer either there - generally you'll go with the one you started with.

The smallest of the PICs - tiny 6- or 8-pin PIC10 and PIC12 series - are kinda fascinating. Cheap as dirt (less than 1€ in single units), and still relatively powerful, but they have some interesting quirks that can make them a bit difficult to use.

I first used these close to ten years ago (based on datecode on chips I have remaining) for a small project to control car's interior lights. After some digging I found the PICkit1 programmer I used back then. It could program PIC12 natively but PIC10 has different pinout so adapter was required, it's still attached as you can see. Not pretty but good enough.


Since I'm using PICkit 3 now, I needed a new adapter. That was simple enough build; small piece of board with headers and some wire. Black/red are the external power leads as you might have guessed. The board has headers for either 8-pin PIC10 (specifically PIC10F206) or PIC12 (PIC12F509) chip (these were the types I had available). It may a bit difficult to see in picture but both ends of the cable glued with Epoxy to withstand some minor abuse.


Bottom view. Note 100nF decoupling caps, one for each header between power pins (note that board is upside down). The board I used as base is half of a handy prototyping board I picked up at SP-Elektroniikka, a local electronics component shop.



Next; a bit more about the quirks of these fun little chips

keskiviikko 9. huhtikuuta 2014

This I hate

If your free (as in 'no cost involved') product does this, **** ***. That's all.


This kind of behavior usually makes me to look for different manufacturer, but unfortunately they all appear to be equally bad...

sunnuntai 6. huhtikuuta 2014

TV antenna amplifier


Lots of broken stuff on my hands lately. This time I had some issues with TV reception at our summer home. As in "no signal at all". The cottage is pretty far from transmit station so there is an signal amplifier at the mast, which is powered by feeder unit from inside the cottage.

So, after the usual checks ("plugged in?" "socket works?" "antenna cable okay?" etc) I opened the unit. The problem was apparent quite quickly; two of the transformer's solder joints were both broken. Easy enough fix, but unfortunately I didn't have soldering iron with me, so I had to bring to back. Now joints are fixed (and transformer is glued down to lessen mechanical stress), but whether this helps remains to be seen - unit is now waiting on my desk to be taken back there.


Sorry about the shallow DoF, but there isn't that much interesting stuff going on at the back of the board anyway. The F connector furthest back is "in" connector (so it feeds DC voltage to antenna cable), other two are "out" connectors (to TV and whatnot). There just some capacitors and zero-ohm resistors to pass signal and DC power around.

Closer you can see the transformer pins and next to it simple DC rectifier. Power isn't very smooth, 15v +/- 1v approximately, but it shouldn't matter for a simple amp. And yes, probing the thing while powered made me very uneasy. Those so innocent-looking joints could deliver major pain if I happened to be a bit careless... In the end I covered them with masking tape before doing further measurements. Still not very safe but I got measurements I needed. This definitely is in category of don't try this at home!

Top view below. Nothing but transformer (15v AC out), single smoothing capacitor and metal can.

You can actually see under the can from the openings. There's practically nothing in there - a few jumper wires and inductors, and they only carry the DC voltage. All the actual signal traces are at the bottom of the board, completely unshielded. A bit of "WTF?" if you ask me.

There is a lot of unpopulated places on the board too. I'm guessing that this same board could be used as an standalone amplifier as well, in which case the amplifier circuits would be in currently unpopulated places on board. In that case the metal can would make sense.

So there. Hope this fixes the problem, as the amplifier itself is about 8 metres up from ground (and 3 metres up from the highest roof level), I don't really have any desire to climb there...