perjantai 28. marraskuuta 2014

Bluetooth link

Bluetooth as method to communicate between devices has fairly big stigma of being unreliable. This is not completely undeserved, but based on my observations it is (slowly) getting better. Unfortunately there's still a long way to go.

In my case the link is typically RFCOMM (serial emulation over bluetooth) where a device communicates with PDA or phone. On device side I've used BlueGiga's modules (not the cheapest option) but so far they have never failed me, working perfectly. Not to mention the their iWRAP firmware/command system that is simply pleasure to work with as it does all the hard work for you.

Phones, on the other hand, have been pretty much hopeless. The major issue seems to be their operating systems' bluetooth stack (and/or chipset). After some connect/disconnect cycles (like phone being moved out of range, temporary power losses at device end resetting links and so on) phones traditionally always crap out, requiring at best manual disconnect/reconnect, or at worst power cycling the phone. Not something that I'd like to tell customers to do.

The older Windows Mobile devices are the worst, and unfortunately I still have to deal with them. Daily reboots all the time. Older Nokias (Symbian) were unpredictable. Some models worked fine, others less so. I would have expected them to have common chipset/BT stack but apparently this wasn't the case.
So far I have no experience on Windows Phone so I can't comment on them and Apple's devices still don't support RFCOMM at all (or so I've been told) so they're already lost cause for my use.

Then there's Android. Like Symbian it seems to be hit-or-miss. Older Samsung phone I had (with Android 2.3) was hopeless - connect() would just block forever if it couldn't connect to remote device immediately (and I do mean forever - even if device became available it would never connect and never fail, just block until process was killed). Newer ones seem to be better, for example I surprisingly haven't been able to get Trend Plus (Android 4.1.x if my memory serves) to fail even once (and trust me, I've been abusing it a lot while testing, just like the customers would abuse the link).  I don't have much experience on other manufacturers' devices, but unfortunately the conclusion here still is this:

For BlueTooth use every single phone must be tested and "certified" as usable in our systems. I wish I wouldn't have to do that but until situation on phone end gets better that's just how it must be.



keskiviikko 26. marraskuuta 2014

(Toy) train wreck

Year or two ago we got our kid a Brio toy train set with some length of track and remotely controllable train. Back then it wasn't very interesting (to him) so that got buried for a while, but recently he got interested again, especially after we got him some more track (total length now being around 4 metres or so - fortunately we had one spare room to lay it out).

It was expected that the train would not last long as he likes to stop it by holding it when it's run on motor and pushing it forcefully, straining the gears and the motor. So it was not very surprising that it started to fail relatively quickly, eventually not moving anymore at all (but it still makes usual sounds and so on it electrics wasn't dead).

New ones are a bit expensive so I decided to see what could be done. Some one night the train mysteriously vanished from home (event that didn't go unnoticed by the small one) and was taken apart the next day.

The text on train says Brio RC-101, I tried to look it up but couldn't find it anymore so it might be no longer available (or maybe it's just sold as a set I couldn't find on quick search). I'd expect that newer models are similar in construction, prices for those (just train, no remote) were around 20-30 euros.

First problem was that it was closed with those damn triangle-shaped screws, four of them total. 2mm flat screwdriver can be used to open them, but you need to be very very careful - if the blade slips you will very likely damage the screw head and make rest of the process more difficult, if not impossible (note also that there apparently are several triangle sizes, others may need larger blade).

Inside was motor mechanism - nothing too fancy. I didn't bother to open it further to see the electronics (IR receptor as train is remote controllable, speakers and such) so no pictures of that, sorry. I don't expect them to be too interesting anyway, main chip most likely a COB with glob on top, a few passives, transistors and others and nothing more.


Gearbox comes out easily enough, aside the cover it isn't held in place at all. Fortunately no more fancy screws, gearbox was closed with two phillips-type screws. After popping it open the motor comes out easily enough. And yes, it was the motor that was broken, not the plastic wheels. Those would've been impossible to repair.

Here I have replaced the motor already, original motor is the one that not connected. It was annoyingly small - 8x10x15mm, excluding the shaft, so finding replacement was a bit difficult. I ended up ordering one from dx.com, sku 275090. It isn't exact replacement and most likely runs slower than original but no matter, important thing is that it runs. You can also see that new one is a bit shorter so I had to put in a bit glue to hold it in place. 


And of course despite trying to decipher markings on the motors the first time leads were the wrong and train reversed when it should be driving forward. Not difficult to fix but annoying.

One more picture of motor/gearbox mechanism while open. Note few small metal plates in compartment where the gearbox should be - four of them are used as spacers, placed between the train frame and gearbox. No idea why - maybe they have several gearbox designs, some of which are slightly larger.

Putting it all together was simple enough, and it's alive!


On how long it will last this time, well, your guess is as good as mine...


And somehow I predict that I have train track building duty this evening.

Later addition: After some observation train clearly (to me) is slower and weaker than before, but no matter. It would need 3v motor (train uses 2 AA batteries - replacement motor was 4,5v), but those seem to be even harder to find. Kid doesn't care so no matter, it's fine (and taking abuse just like before, maybe I should start looking for better replacement motor immediately...)


Post mortem seven months later: This train does not a good submarine make. In fact I just found out that water pretty much kills it permanently (not very surprising, really, but apparently this is a very difficult concept for small kids to grasp). All's not lost though, take one plastic gear off from the drive mechanism and you have pushable train instead.
I don't really feel like taking it apart to examine electronics there, since I pretty much expect to find just a small, cheap PCB with single (glob-covered) chip on it with maybe some passives and a speaker. Not very exciting.


maanantai 17. marraskuuta 2014

Serial protocols (part 2)


In previous part I showed few simple cases of serial protocol. Now we'll improve them a bit by adding bit of buffering and simple checksum validation.

Checksum is implemented only on downlink (to Arduino) messages but extending calculation to uplink messages is trivial. This program does nothing but acknowledge messages with valid checksum; invalid checksum results NAK and too short message is ignored.

Side note on code comments; The code here is definitely not example on how you should comment your code. Since this is a tutorial I've chosen to focus most explanations and discussion on the main text, mostly because the topic itself requires way more explanation than I would normally put in code (typically I add "why" comments, but explanations here would add major "how exactly" part too -  of which the latter is in my opinion bad in living production code)

char recvBuff[4];
char recvLen = 0;

// Function to calculate checksum. Simple XOR sum is used.
unsigned char calcMsgSum(char *buff, int len)
{
  unsigned char sum = 0x77; 
  unsigned int i;
  for (i = 0; i < len; ++i)
    sum ^= buff[i];
  if ((sum == 13) || (sum == 10)) // Trivia for reader: Why is this here?
    sum += 10;
  return sum;
}
 
void loop()
{
  if (Serial.available() > 0) {
    char c = Serial.read();
    
    if (c == 10) {
      // LF ignored
      
    } else if (c == 13) {
      // CR used as end of line
      
      // Minimum of two characters required; data and checksum
      if (recvLen > 1) {
         // Verify received checksum against calculated
        unsigned char msgSum = calcMsgSum(recvBuff, recvLen-1);
        if (msgSum == recvBuff[recvLen-1]) {
          // For this example we do nothing but acknowledge message.
          Serial.write("A\r");  
        } else {
          Serial.write("N\r");  
        }
        
      }       
      recvLen = 0; // clear buffer for next command      
      
    } else {
      // Not CR or LF; store received char to buffer. 
      // There is never, I repeat, *NEVER* an excuse to not check your buffers. Always do it.
      if (recvLen < sizeof(recvBuff)) { 
        recvBuff[recvLen] = c;
        ++recvLen;
      }
    }
  }
}

Some test strings, including checksum character: "D3", "VER6" (calculated manually so I'm not 100% sure of correctness)

The checksum used here is simple XOR-sum. As a checksum algorithm XOR sum is fairly weak compared to, say, CRC but it is simple and quick to write so it is used as an example. Naturally the sender must have (functionally) equal checksum calculation routine to calculate it when building messages. Checksums in general are not topic here so I'll keep using this same XOR algorithm in my examples to keep them (more) simple.

Data itself is simple format; first data (max 3 bytes), then checksum (1 byte) and message is terminated with CR. LF character (which may be added by some terminal programs) is ignored.
This of course means that CR or LF characters may not appear in main message data. Using CR allows easy testing with simple terminal program (aside checksum calculation).

Note the buffer checking; if you don't do it already, build a habit of ALWAYS - with absolutely no exceptions - checking your buffers when dealing with incoming data. It does not matter where the data is coming from - even data internal to your system can get corrupted. C gets bad enough rep on this already so do your part to keep things tidy and safe. </rant>

When code were to receive too many characters you'd normally want to mark message invalid without bothering with further processing (received message will be invalid anyway), this code doesn't do that (again, to keep things simpler) but that isn't difficult to do.


But what if you want to transfer arbitrary binary data - likely including CR/LF characters - over the link? Escape characters will help you. In this example we map character 127 (0x7F) to mean that following character is data and not control data (changed part in blue).

unsigned char nextIsEscaped = 0; // We need flag for signalling this
  
void loop()
{
  if (Serial.available() > 0) {
    char c = Serial.read();
    
    if (nextIsEscaped) {
      if (recvLen < sizeof(recvBuff)) { // escaped data character - add to buffer
        recvBuff[recvLen] = c;
        ++recvLen;
      }
      nextIsEscaped = 0;
      
    } else if (c == 0x7F) {
      nextIsEscaped = 1;
      
    } else if (c == 10) {
      // LF ignored
      
    } else if (c == 13) {
      // CR used as end of line
      
      // Minimum of two characters required; data and checksum
      if (recvLen > 1) {
         // Verify received checksum against calculated
        unsigned char msgSum = calcMsgSum(recvBuff, recvLen-1);
        if (msgSum == recvBuff[recvLen-1]) {
          // For this example we do nothing but acknowledge message.
          Serial.write("A\r");  
        } else {
          Serial.write("N\r");  
        }
        
      }       
      recvLen = 0; // clear buffer for next command      
    } else {
      // Not escape char, CR or LF; store received char to buffer. 
      // There is never, I repeat, *NEVER* an excuse to not check your buffers. Always do it.
      if (recvLen < sizeof(recvBuff)) { 
        recvBuff[recvLen] = c;
        ++recvLen;
      }
    }
  }
}

So, now if we receive 0x7F character the system state is updated so that next incoming character will always be interpreted as data and not control character. Since our control characters here are CR, LF and 0x7F the sending system must always escape these characters before sending them as part of data. Checksum byte is also data and needs to be escaped. Note however that transmit side must calculate the checksum before doing the escaping to the message.

Also, remember those two lines in earlier checksum calculation marked as "trivia"? Those aren't needed anymore here (but they don't hurt much either if left there).

Unfortunately this change actually reduces out checksum's effectiveness a bit since now the checksum verifies the unescaped string and not the actually received bytes. In practice the reduced effectiveness most likely does not matter, but is still is worth noting.

Another thing to note is that neither lack of ignore-message-on-overflow and weak checksum calculations are security (as in "blackhat-looking-to-0wn-device") issues; it's up to next level message parser to make sure that invalid messages (be it accidental or intentional) are detected and rejected.

So I leave you here for a while. Hopefully I'll get to writing next part quicker than this, and there's still a lot to improve here and so far we've only tackled one part - transmit errors - of the communication protocol.


torstai 6. marraskuuta 2014

Serial protocols

I know I promised examples of serial protocols but I've been way too busy to write lately. Sorry about that. I managed to start with the most simple protocols so here is the first part.

For simplicity I am writing these to Arduino using its built-in USB (and yes, I'm aware that this messes with my point of reliability -  but these are simple examples for learning that can be copied and tested easily and quickly so bear with me here).

I'm focusing here on three-wire (ground, transmit, receive) type serial link with parameters 9600 8N1 (9600bps, 8 data bits, no parity, 1 stop bit) since that is the type I use the most. Usually MCUs can also provide hardware flow control and some other control mechanisms (like parity for simple bit-error detection) that can be used to make link more reliable and controllable, depending on your exact situation.

After loading the sketch to Arduino you can use your favorite serial terminal program to send commands to it - I've written custom one that handles some custom protocols I often use but there are many terminals available for free, for example termite that I'm linking here because happened to be on top of quick google search and it seemed actually useful, unlike few other top links.
( http://www.compuphase.com/software_termite.htm ).

Basic Arduino doesn't have much in way of easily visualized I/O so I'm using the "L" led and serial return channel as example of work done. In case of serial return channel I'll make note when data is part of protocol or just example (typically written on paper/screen/whatever and not seen by controller).

So to the code. First basic setup phase; use built-in routines to initialize serial port and set pin 13 (tied to L led) to output. Led will turn on when pin is driven high.

void setup() 
{
   // Init serial communication, 9600 8N1
  Serial.begin(9600);

   // Init L led, set off
  pinMode(13, OUTPUT);
  digitalWrite(13, LOW);
}

Then the main loop, starting with as simple code as possible.

void loop()
{
  if (Serial.available() > 0) {
    int c = Serial.read();
    
    if (c == '1') {
      digitalWrite(13, HIGH);
    }
    if (c == '0') {
      digitalWrite(13, LOW);
    }
  }
}

Arduino is simply listening to incoming data and acting on it by setting LED on when '1' is received or off when '0' is received. There is no error checking or acknowledgements of any kind, so controller can't know if device actually receives the commands.
For controlling a simple lamp (or relay or really anything that is either on or off) this may actually be "good enough". If link is "lossy" controller can simply send the same command multiple times, hoping the at least one is received successfully.

This protocol works (kinda-sorta) but is quite fragile. What happens if wire is cut? So let's add simple acknowledge mechanism; received send A when command is received and N if command is bad.

void loop()
{
  if (Serial.available() > 0) {
    int c = Serial.read();
    
    if (c == '1') {
      digitalWrite(13, HIGH);
      Serial.write('A');
    } else if (c == '0') {
      digitalWrite(13, LOW);
      Serial.write('A');
    } else {
      Serial.write('N');
    }
  }
}

Now controller can listen to returning data and react on it. If no reply or NAK ("negative acknowledge") is received the command is can be sent again. Now we can detect more error situations and even report such cases to user.

Note that the difference between '1' and '0' commands used above is only single bit. One bit can get corrupted easily, so unless other kind of error detection is used, you'd want to use command bytes with more difference. For example 0x30 ('0') for off, and 0x55 ('U') for on (four-bit difference; transfer errors should usually result NAK)

(excercise: what is the difference between 'A' and 'N', in bits, and is there need to use other bytes for those replies?)

Now, when you want to control LED these can be used, but how about when you want to check if the LED controller is alive? Let's add quick query command;

void loop()
{
  if (Serial.available() > 0) {
    int c = Serial.read();
    
    if (c == '?') {
      Serial.write('A'); 
    } else if (c == '1') {
      digitalWrite(13, HIGH);
      Serial.write('A');
    } else if (c == '0') {
      digitalWrite(13, LOW);
      Serial.write('A');
    } else {
      Serial.write('N');
    }
  }
}

So now controller can probe the device ("are you there?" "yup") when say starting up and report status to user without affecting the system state. Simple addition but so very useful.

On next post I'll be continuing from here, when I find some time of course. That unfortunately might take a while, since I'm (still) quite busy and the protocols introduced next will take some time to write and test too.

maanantai 3. marraskuuta 2014

Courier services


I've never been too much a fan of DHL or UPS, now even more so. This time
it was DHL that managed to pretty much destroy this meter.


Surprisingly, after I managed to rip open the enclosure (mind you, that is 1mm thick aluminium so it has taken some serious beating to bend it this badly) and get to the electronics it still works. The PCB is however so badly bent it's unusable for any real use.

Update: DHL denies any responsibility since I apparently didn't report it damaged on arrival. Well, no, the box the meter came in was only slightly deformed, like something not-that-heavy (just 20kg or so) had been on top of it. Also the box was way larger than the meter so there should have been plenty of space for meter to be move around inside so that is what I expected to have happened (and yes, it was wrapped on bubble sheets).

I have pretty good idea on what it will take to damage the meter and really, arrived package didn't look that bad. Just for fun I tried to stand on the empty aluminium enclosure diagonally (on part that was bent - no PCB inside so it's even weaker than when assembled). I weigh around 70kg but that only bent the enclosure about 2mm inward. Not even close to damage seen here. Pretty much what I expected to happen.

They must have driven a friggin' forklift over the package, with meter caught just right inside it to cause this kind of damage.

While they're technically right - I did accept the damaged package - with that denial they also just lost any change of ever getting my business ever again.



torstai 23. lokakuuta 2014

No wonder it didn't work


When the parameter download to device failed, I pretty much knew where the problem is. Visual inspection only confirmed the suspicion:


Not very good photo, I know, but without macro lens this is just about best I could do. Maybe I should try to build some kind of adapter so I could attach camera to the microscope...

Yes, it's typical serial EEPROM on I2C bus. One leg raised (VCC), another just barely soldered. Easily fixed and good to go.

Which allows me to awkwardly transit to another serial item, RS232 I praised previously. Soon(-ish, time allowing) I'll be posting some simple code examples on how to build communication between two devices with increasing complexity and safety.


tiistai 14. lokakuuta 2014

Ode to RS-232


The RS-232 serial communications was first introduced in 1960s (and amended and changed numerous times after that) and its death has been proclaimed over and over again, lately by ubiquitous USB. New computers haven't shipped with RS-232 ports for years now, unless you deliberately seek out specialized motherboards for some extra cash.

On paper just about anything else is superior to RS-232. Data speed is very limited. It is point-to-point link (no multiple devices on same wire). And cable length will quickly limit transmit rate even further. And so on and on.

Yet I still find myself building RS-232 cables even today. Simply because one very - nay, extremely - important factor:

It just works.


Just about my entire career I've been dealing with devices that carry certain expectations. When customer pays more than 100k€ for device, you just can't tell them to turn it off and then on again, just because some stupid peripheral device connected internally with USB decided to crap out. Dealing with that was one of my first lessons on reliability (*snicker*) of USB. Not exactly fun, and when dealing with COTS components, not much you can do about it either. But somehow we managed.

Lately the price tag of devices I work with is smaller but issues are the same. When USB link hiccups, it just doesn't reset itself and carry on, but it will need to explicitly power cycled to recover. Small thing but still annoying, and frustrating to user (even if the reset itself happens automatically and semi-transparently).

Granted, RS-232 isn't immune to broken connection problems either, but at least it is easy (relatively speaking) to build fail-safes and recovery to protocol code, and I have to admit, a lot of my protocol code is fairly paranoid nowadays, at least in places where it matters. Framing, timeouts, connection resets and what not everywhere.

Now someone might ask why don't I use CAN or other such bus that is designed for reliability. The answer is availability. RS-232 is everywhere. Every single MCU you pick (except maybe the tiniest ones like PIC10 I wrote about earlier) will have it. All you have to do is connect two (or three) wires and write simple routines (typically about 20-30 lines of C - and I mean C that directly uses hardware registers, no libraries involved) and you will be good to go (okay, you might need MAX2323 or other such chip there somewhere unless you want to fiddle with (LV)TTL link - and for reliability some nicer protocol on top, but sometimes simple commands is all you need to hack something together).

So there, you'll have to pry RS-232 link from my cold, dead fingers before I'll give it up. Because there is nothing that can beat its simplicity and reliability.




sunnuntai 12. lokakuuta 2014

JKartta update - import your custom maps


Since last time I've implemented GPX data import/export and more interestingly ability to use your own custom maps (imported in slightly modified MapInfo .tab format) with the app. With that addition I felt that I could publish the app in Jolla store, however I ran into slight snag; Translations.

So far the app has used exclusively Finnish map data, and thus there really was no need to support anything else but Finnish language. Now with custom maps it became usable elsewhere too, but I hadn't really though of translations yet.

Fortunately there weren't that many texts so adding English translations didn't take long (granted, translating main help/manual file is still work in progress). There just seems to be fun bug in Sailfish that prevents applications from automatically detecting current UI language with usual methods (QLocale::system() and getenv()). So far I haven't found any (sane) workarounds either.

Damn. Oh well, the version with map import can be (soon) downloaded from http://www.trippi.fi, as long as you can tolerate it speaking (umm.. reading?) Finnish to you. We'll see how it goes with the official store.


torstai 2. lokakuuta 2014

JKartta officially


Now it's (a bit more) official.



JKartta main page (page in Finnish; since this is about Finnish topological maps I'd expect not many foreigners are that interested, although it might come in handy if you are into hiking for example)

Now then, why am I writing this in English? Well, the app definitely isn't finished yet. Something I'd like to add at some point;

On-screen compass
Resuming previous track (after shutting phone down for overnight stay)
Reducing power consumption (I suspect there are many unnecessary screen updates, especially when phone's screen is off)
OpenStreepMap integration (it's already partially done although very glitchy; if I'd also have access to tile server this would allow me to make that part of software free)
Overlays (custom highlighting on top of map, like allowed hunting regions, or own map tiles)
...And whatever I feel like adding yet



tiistai 23. syyskuuta 2014

Fakin' it (quick note)

( Previous part here )

As per original intent of this blog I'm just quickly adding this idea here.

Okay then. In earlier parts I mentioned changing duty cycle and problems it will cause. Now, if we take short enough buffer of pulses - let's say 3-7 full pulses - the figures become meaningful again. During normal driving the change of speed (ie. pulse duration/duty cycle) should not be that quick and the pulses should be fairly similar, so spurious (artificial) pulse should be fairly obvious.

Mind you, first spurious pulse should not be enough to raise a red flag - that could be caused by sudden braking or quick acceleration (or losing grip momentarily, like in winter). Variation in pulses when speed is relatively constant, now that might be an issue.

One red flag is too constant pulse though - if the speed remains same for entire drive, there absolutely is something wrong. Picking up customers, turns, traffic lights, stopping at destination - all that causes variation. And by entire drive I mean entire drive, not just long parts of it - driver may just be using cruise on empty main road.

And then there just could be speed indication on meter's display, along with the fare reading.

torstai 18. syyskuuta 2014

JKartta on täällä! (in finnish)

This is - I think - mostly of interest to Finnish people so this time I'm writing in Finnish. In short, I feel that I can now release the map app I've been working on. Since the material covered is Finland and the app itself is in Finnish I expect that it isn't that interesting for people elsewhere -- unless I get around to implementing OpenStreetMap support some day.

Ja sitten itse asia suomeksi.


Ainakin minulle Jolla-puhelimessa suurimpia ongelmia on ollut kunnon maastokarttaohjelman puute. Käsittääkseni ainakin toisen näistä toisilla alustoilla olevista saisi toimimaan kikkailulla kolmannen osapuolen kauppojen kanssa, mutta siihen ei huvittanut lähteä joten päätin sitten noin oman huvin ja hyödyn vuoksi (jos ei muuta niin tulipa opeteltua Qt:n ja QML:n käyttöä) askarrella Jollalle natiiviapplikaation.

Alun perin lähtökohtana oli Maanmittauslaitoksen avoin aineisto, mutta kun harrastuksiin kuuluu mm. metsästys ja metsänhoito, avoimeen aineistoon liittyi iso paha puute - rajatiedot. Niitä ei ole saatavissa avoimessa aineistossa vaan ne täytyy lisensoida mikä tietysti kustantaa jonkin verran.

Näinpä päätin sitten tehdä ohjelmasta saman tien laajempaan jakeluun soveltuvan, missä tietysti pienenä hankaluutena on jakelu - Jollan app store ei toistaiseksi ainakaan tue maksullisia ohjelmia. Joten vaihtoehdoksi ei oikein jää kuin hoitaa tuo puoli itse toistaiseksi, ja miettiä asiaa uudestaan sitten kun tilanne virallisen kaupan osalta muuttuu.

Nyt ohjelma (mielikuvituksellisesti nimettynä JKartta) on sitten siinä kunnossa että uskallan tuota tarjota rajallisesti koekäyttöön, oman palvelimen kautta toimitettuna ja pykälää verran tavallista app storea vaikeammin laskutettuna (käytännössä pankkisiirrolla).

Sitten esimerkkikuvaa ohjelmasta. Tässä on käytössä ohjelman oletusasetuksena oleva 1:20000 mittakaava, jolloin puhelimen ruudulle mahtuu noin 1050x1900 metriä karttaa. Alareunan tummennetulle alueelle tulevat viestit (ja jos mitään näytettävää ei siellä ole, ei ole tummennustakaan), ja tässä punainen pallo kertoo myös että GPS:llä saatu sijainti on ruudun ulkopuolella; palloa koskettamalla kartta keskitetään nykyiseen sijaintiin.
Harmaa "merkki" keskellä ruutua on talletettu huomiopiste. Huomiopisteet voi (tällä hetkellä) lisätä vain käsin, joko ruudulla näkyvään kohtaan tai koordinaattien perusteella jonnekin toisaalle. GPX-importti ei olisi iso työ (nykyinen toteutus osaa jo kuljetun matkan mittauksen ja reitin näytön; se osaisi periaattessa näyttää jo talletetut reititkin mutta reittien talletus/lataus vielä puuttuu) mutta nämä joutuvat vielä vähän odottamaan.




Alla on käytössä mittakaava 1:10000, ruudulla näkyy tällöin n. 530x950 metriä (tarkat lukemat pitäisi tarkistaa ja laskea taulukoista, nämä mitat ovat kuitenkin "tarpeeksi lähellä"). Olen omalta osaltani todennut että tuo 1:20k mittakaava on yleensä maastossa käyttökelpoisin.


Ohjelman hinta koostuu suoraan ladatuista karttaruuduista - ruudulle mahtuu hiukan tilanteesta riippuen enimmillään 15 kappaletta (joista osa ei tietenkään näy kokonaan). Ensimäisen kerran käynnistettäessä ohjelma lataa vain näytön keskimäisen ruudun automaatisesti mutta tämän asetuksen voi halutessaan muuttaa, joko 1x1, 3x3 tai kaikki näytöllä vähänkään olevat ruudut. Ladatut ruudut tietysti säilyvät puhelimen muistissa jotta niitä ei tarvitse ladata enää uudestaan.

Ja vielä esimerkki tapauksesta jossa vain kolme karttaruutua on ladattuna. Näinkin ohjelmaa voi käyttää mutta rajallinen kartan näkyvyys tekee navigoinnin (maamerkkien vertaamisen) vaikeammaksi. Tästä näkee myös hyvin yhden karttaruudun koon; nämäkin siis 1:20000 mittakaavalla jossa yhden karttaruudun alue on n. 250x250 metriä.

Tällä hetkellä hinnaksi asettuu 20€ (sis ALV 24%) per 200 karttaruutua. Vaikka ohjelmaan luultavasti tulee lisäominaisuuksia jatkossa (kompassi, GPX-import yms yms), jo ostetut ruudut eivät katoa.
Käyttäjätunnuksia (sekä tietysti itse ohjelmaa) ja lisätietoja voi kysyä esim. sähköpostilla; toni piste rasanen at trippi piste fi .


Rant: Appliance UI

At the moment a certain large European brand is running an advert that (to paraphrase) says that whenever there is a problem, they'll think up a solution. This time the solution appears to be clay. In a dishwasher. Why exactly would anyone knowingly add clay to their clothes, or to their dishes is beyond me, but then again, they don't say it's clay, they use the "nicer" name. But I digress, I have something else in mind (granted, distantly related.)

We have washing machine/dryer combination made by this same company I referred above. Remember the slogan, (again paraphrasing) "problem? we'll think of the solution". Well, it certainly seems that exactly none of their engineers responsible of this trainwreck of an user interface have any children.

As evidence I present you the interface of the washing machine (with manufacturer and models photoshopped out)


Pretty nice in general. Select general program with the wheel. Do necessary adjustment with following buttons, then start with that nice large button at right. Full of nice, bright controls that you can twist or push. Even when the program is running. And twisting that very easily accessible wheel, even a bit, will permanently cancel current washing program.

The thing about children - especially toddlers - is that they are very very curious. Nice bright lights? That will draw their attention. And if that wheel is touched, well, goodbye program, the only option is to start all over again. Even if program was two thirds - or seven eights - or or ... -- of the way through. Just because someone came and touched the damn wheel. Absolutely no way to resume or even know how far the program was.

This is not good UI design. This is very very bad UI design. Insanely bad design. Shame on you, company-that-I-refuse-to-name-here.

Now, compare it to our Rosenlew dishwasher (no photo of that, sorry). If a program is running, you have to press and hold two buttons down for about five seconds to cancel it. And cancelled I have, many many times when the said toddler has managed to start washing cycle on that dishwasher. But so far he never ever has managed to stop ongoing program. I have had to turn the washer on a few times (even then it resumes from previous state - exactly as one would expect!) but either way, much much better than the stupid washing machine.



tiistai 9. syyskuuta 2014

Dead.


It was bound to happen some day. I had some documents with me on an USB stick and when I come bad home it doesn't work anymore. Not even a blib. Completely dead.

Damn. That was my favorite USB stick, size and shape were close to perfect; not too small to get lost, not too bulky to cause problems when using or carrying it. Oh well. Time to go shopping again.


Fortunately there wasn't anything that critical on it so loss isn't that big deal. I didn't really have any expectations about recovering it but I cracked it open anyway, primarily to see what's inside.

As it turns out, not much. Other size of the PCB is fully taken by single 64Gbit  (8 GByte) flash chip, other side has controller (SM321QF - based on quick googling not very trustworhy chip), crystal and some passives. Measurement only confirmed what I expected, that is, it's dead, for good.

The other stick above it is one that I have used in car player, here only for reference. It's perfect there - small form factor, doesn't stick out from radio's front panel and doesn't draw wrong kind of attention (although who in his right mind would bother to steal El Cheapo-brand car player anyway...).
What I'm more amazed is how they have managed to fit same 8Gbytes of memory on such a small space, comparing to one below. I kinda suspect the size is "bought" with high cost of long-time reliability, so even more reason not to use it for anything critical. We'll see when it dies...

Oh, and when I said there wasn't anything critical on dead stick I lied a bit. There wasn't anything critical in sense of "data I can't afford to lose". There was some stuff in sense of "documents I don't want to get to wrong hands".


I'm pretty sure that now it's unrecoverable enough.

maanantai 1. syyskuuta 2014

Fakin' it (part 3)


Previous parts here and here.

Previously I've thrown in some ideas considering speed signal tampering that some less than honest drivers may be employing. This series is primarily focused on what kind of signals to expect and low-cost tampering detection on cheap(ish) MCU. So now it's time for some actual code to do the magic (or the difficult part of it, at least).

Let's start with constraints. Cars typically generate between 1000 and 28000 pulses per kilometer (mostly depending on manufacturer), or 1 to 28 pulses per meter. Lower bound that interests us is, say, 20km/h, and upper for example at 200km/h. So valid frequency range is from 5.5 Hz to 1.5 kHz (roughly).

To make any judgement on pulse length the timer resolution will need to be at least one decade, preferably two above these, so we'll want our timer that does the measurement to run at approximately 150kHz. This pretty much rules out interrupts, there is no way you could get acceptable performance from any (microcontroller) software at that rate.

Fortunately most MCUs expose the underlying accumulator counter that is used to set timer interrupt periods, so we can use that to our advantage. For quick test I used a PIC24-based board I happened to have handily available. The processor (specific model not that important) has main oscillator at 8 MHz and has 5 timers, of which only one was used. So I chose to implement this measurement system using Timer 2 of the MCU.

PIC24's timers come with prescaler that is used to scale down the main oscillator frequency. In this case 1:64 prescaler gives us 125kHz resolution which is close enough to previously calculated 150kHz so we can work with it. Since the counter is 16-bit, this gives us minimum frequency of 1.9 Hz so lower bound is no problem either - anything slower is too slow to be indication of tampering (in this application at least).

So, variables and initialization of timer and the ISR (I'm using MPLAB X as IDE and Microchip's C compilers here);

// Calculate new value if these are set
volatile unsigned int tmrAccStop, tmrAccCnt; 
// Accumulator in interrupt 
volatile unsigned int tmrAccCntInt; 

void timer2Init()
{
  T2CON = 0; // stop timer, reset control reg
  TMR2 = 0; // clear timer acc register
  PR2 = 65535; // period; set to maximum 16-bit value
  IPC1bits.T2IP = 1; // interrupt priority
  IFS0bits.T2IF = 0; // clear interrupt status flag
  IEC0bits.T2IE = 1; // enable timer1 int

   // TON=1 - start timer
   // TCKPS=2 (1:64) - prescaler
  T2CON = (1<<15) | (2<<4);
}

void __attribute__((interrupt, auto_psv, shadow)) _T2Interrupt(void)
{
  ++tmrAccCntInt;
  IFS0bits.T2IF = 0;
}

Since we are mostly interested of first period, if the tmrAccCntInt variable is set it can simply be used as indication that pulse period was longer than our lower bound and further processing is not needed.

Then the IO Change Notification interrupt (I'm not including IO setup since there's nothing special there);

void __attribute__((interrupt, auto_psv, shadow)) _CNInterrupt(void)
{
  // Change notification is signalled on both rising and lowering edge. 
  // Here we want just rising edge, so checking for it.
  // By triggering on both rising and lowering edge you could easily add 
  // duty cycle measurement too.
  if (PORTE & 2) // Pin E1
    { tmrAccStop = TMR2;
      TMR2 = 0;
       // Counter; if non-zero, timer has overflowed  
       // so rate is lower than 1,9Hz (approx)
      tmrAccCnt = tmrAccCntInt;           
      tmrAccCntInt = 0;  // Clear internal counter
    }
 
  IFS1bits.CNIF = 0; // clear Input Change Notification
}

Since we are not sharing Timer2 with other functions we can simply clear its accumulator in interrupt. This makes the following math a bit easier since we don't have to deal with partial periods or timer overflows.

Note that I didn't put any math in interrupt. In this example involved math is very light, but nevertheless, in general rule you should never do any complex math in interrupts if you can avoid it; store results to suitable temporaries and do the math in main() to make time spent in interrupts lower.

Then the main loop (again, I'm excluding setup since with exception of parts listed above it's pretty trivial);

  while (1)
    {
      unsigned int n, end;

      __asm__ volatile("disi #0x3FFF"); // Disable interrupts

      if (tmrAccStop != 0xffff) // if not ffff, we have new reading ready.
        {
          n = tmrAccCnt;
          end = tmrAccStop;

          tmrAccStop = 0xffff; // clear reading for next
        }
      else
        {
          end = 0xffff; // no new reading; don't do anything.
        }

      __asm__ volatile("disi #0x0"); // Enable interrupts.

       // It would be possible to do entire analysis with interrupts disabled
       // but I prefer to make critical sections as short as possible for same
       // reason I don't do math in interrupts.

      if (end != 0xffff)
        {        
          if ( (n > 0) || (end > 65000) )
            { // Timer interrupt triggered or period long enough; can be ignored
              debugWrite("no event\r");
            }
          else
            {  
              debugWriteInt("period=", end);
            }
        }
    }

DebugWrite functions are simple utility functions that write given string and data to serial output. Nothing fancy in there.

Yes, since stop isn't initialized this will trigger spurious first reading. Yes, this will also miss readings if  main doesn't run fast enough. And the end result isn't exactly useful alone. And I'm not sure if this even compiles as this is a copy-pate from several thousands of lines long project I am using to quickly test these ideas. But this shows you how to measure shorter signal periods that typical interrupts allow, and further refinement of results aren't exactly rocket science either.

Happy hunting :)



keskiviikko 27. elokuuta 2014

Fakin' it (part 2)


This is part 2 of previous text, Fakin' it I wrote earlier. Previous text was mostly theoretical ideas, now after some more thought it's time for more in-depth look in signal analysis.

When doing theoretical work the detailed signal analysis always looks very tempting. Analyze incoming signal, detect some parameters (levels, period, duty cycle and whatnot) and if something is off you signal upper level that tampering is detected, stop everything!

Unfortunately, it seems that in many many vehicles the duty cycle of the signal isn't 50%, and it also depends on the speed of vehicle:

I remember some older MB, possibly C or E series, back when they weren't using exclusively CAN. Its signal wasn't your typical pulse train, but it was kinda sawtooth-ish; it rose at roughly logarithmic rate  (x millivolts per y milliseconds at low voltages where the threshold usually is) and was then pulled down (almost) instantly. As you can guess the duty cycle will vary wildly depending on the speed, as well as the average level of signal.

Another case; Some time ago I was doing diagnostic on an MB van as the pulse was completely gone (exact car model escapes me and is really not that important). Like so often, when I removed the panels so I could probe the incoming signal the problem went away so it must have been bad contact somewhere, but here the signal itself turned out to be more interesting.

As standard diagnostic I attached portable oscilloscope to the signal and drove a bit around (well, the car's owner drove, I monitored the signal). At the moment I didn't pay attention to specifics as I was still in full troubleshooting mode, but later I started thinking the details and realized its importance relating to this issue.

Firstly, the active period of signal was fairly constant, approx 5ms, regardless of the speed driven (granted, we didn't drive very fast - 50 km/h or so tops). This of course means that inactive period was changing. Additionally at slow speeds the inactive period was low and active period high; but when speed crossed certain threshold (I didn't pay enough attention to take note of exact speed but it was around 20-30km/h) that reversed; inactive high, active low. So this pretty much throws out duty cycle based tampering monitoring.

Now, although both examples I listed here were made by MB those are not only ones where these issues rise.

So, what we are left with? Pretty much all we have left is signal period (unless you want to implement some kind of manual configuration or auto-detection on signal features you wish to monitor; that is certainly possible, but I foresee so many problems there so I'd prefer to stay away from that particular can of worms. Just trust me on this.)
 
Next time; practical software example.


perjantai 8. elokuuta 2014

Pick'n'place'd wrong

Well, it's been a while since last posting. I'm a bit short on ideas right now but maybe I'll think up something more interesting soon.

Now, on lighter note. Today electronics is typically assembled by large 'pick and place' machines, and they really are fascinating to watch when going at full speed. Sometimes of course accidents happen - components are dropped (although I think modern machines note this and place them again), components placed in wrong way (just slightly skewed, or rotated 90 or 180 degrees so at quick glance you won't notice anything wrong) and end result is non-working (or in worst case, burned) board.

As it happens, sometimes they get through the first inspection. This is why I test every single device I deliver myself before packaging it for delivery (volume isn't that high so it isn't too much strain). Typically defects aren't anything exciting - component missing, bad solder joint or whatnot. But sometimes they get... interesting.

Take your typical SOT23-3 package, pictured here. It has three leads and isn't even symmetrical. It should not even be possible to place it on board wrong, at least in a way that would pass visual inspection.

The device I had on hand failed one certain test, so I started checking the section of the board that might be responsible for the problem. I'll always start with visual inspection with microscope, and when passing by certain component in SOT23-3 package something seemed odd. I couldn't instantly figure out what, exactly it was so I picked the board up and started viewing it from angle. That's when I started to see it...



(No, it wasn't the board or component pictured above; picture here is simulated situation. And unfortunately not very good picture either, sorry about that)

Component was upside-down, leads pointing up from board and thus not even touching the pads. No wonder it didn't work right. I had to laugh for that (which immediately prompted dry "guess he found the problem" from next desk)

How? This specific board was flow-soldered, which means that every component is glued in place with a small dab of glue and then dipped (upside down, hence the glue - otherwise components would fall out) in molten solder which will solder all components. The problem with that technique is that sometimes some leads are left without solder which in real PITA - module passes all tests but then starts acting out several months after delivery when component shifts ever-so-slightly.

Oh, and after flipping the component over it worked perfectly, and for what I know the device is still in use somewhere.



perjantai 27. kesäkuuta 2014

"Old" and "young" programmers

I started programming more than 20 years ago now, maybe 25. I don't really count the early meddling with Sinclair Spectrum's basic, or later with GW Basic programming since although I was learning something I didn't really have any grasp on topics so I don't think that really counts. It was only later when I "outgrew" those and moved onto Pascal (Turbo Pascal more specifically) I started really developing as developer.
What originally pulled me in programming was games (surprise! yeah, not really). I just wanted to create something like Ultima V (first game I really finished, albeit with some external help since my English was pretty bad at the time). Back then I was just struggling with very basics of GW Basic so anything serious was way out of my reach, but anyway, I dived in with enthusiasm, never really planning ahead, just starting to write code with nothing more than vague, not-really-fully-formed idea what I wanted to do. And that was fun!

Granted, ofter I ran in unexpected problems, like after I wrote a full game engine but kinda missed writing in the actual game. But it looked good (and still does, even today, even if it's just 320x200).

Then came the professional era. Apparently some people have energy to work with their hobby projects after day of work, but I've found out that I'm not one of them. After full day of coding (and I was full-time coder for a long time) I just didn't have any energy for side projects.

Fast forward to this day. Occasionally there are times there's no need to even think about the code at work so after day or two of that I find myself interested of working on my own projects again. There are few ideas (games) I've been toying with, in my head, for a long time so now that I could do hobby programming again I started with them.

But now there's something fundamentally different.

I just can't dive in anymore like in those days long gone. I need a plan.

That's the difference. The young me could just dive in, start writing code, then rework (I don't want to use work "refactor" here, that concept is too sophisticated for situation being described) until it did what was needed - and typically nothing more.

The old me just can't do that. Here is problem at hand - the game is in 3D world with objects, both static and moving - and right here my mind immediately starts breaking this in smaller parts. World itself, models moving in it, how to make it efficient, and everything related...The depth of the problem is opening in front of my mind eyes, and seeing everything that needs to be done appears to be a very strong demotivator. So much that needs to be done before there is anything... And this is ignoring all the cool stuff shaders can do that I'm not even aware yet.

I didn't really realize this when doing work stuff. Most likely because the change has been gradual. But since I took a very long break with hobby projects the change there is quite glaring, which made me to come to this (most likely overly simplified) realization:

Young coders will dive straight in with enthusiasm. You give them a problem and they go for it, producing a lot of code in short time. Lots of code, lots of check-ins, lots of hours worked and low pay. As a company you'll love these young guys!

Old coders plan. You give them a problem and few moments later they come back to ask questions. Questions you didn't really want to hear, like operating constraints. Details that should be irrelevant by business standards. If they are really experienced they want them in writing, as official specifications. Damn these annoying geezers, why can't they just do what they're told...

Do I regret becoming "old"? Hell no. Life's too short to (re)write same poorly thought out code half a dozen times.

Albeit sometimes I do miss the simpler times.

sunnuntai 22. kesäkuuta 2014

Paperclip to the rescue!


Somewhat offtopic, but ain't I feeling like regular MacGyver now.

I just took a vacation. With small children this means lots of props, including the stroller (or cart, whichever term you prefer). Strollers, of course, are large, heavy, unwieldy and in general a PITA when flying.

Just when I stepped outside the terminal at the destination with my luggage on other hand and stroller on other the strap of the stroller bag broke. So here I am, in 28 degree Centigrade heat, in middle of thousands of other busy people, just in front of terminal doors, with now even more PITA-ish stroller on ground. Damn.

One thing I never travel without is some sturdy string (I'll get to some other necessities a bit later). I was almost opening my luggage to dig for it when I noted a large-ish paperclip on the ground, in exact same position the stroller broke on. At least some luck!

So, just few bends and moments later the bag was almost good as new.


This wasn't the first time traveling with that stroller, so it had taken some beating already. When packing stroller for return trip I noticed that zipper was broken too - the metal part that moves (no idea what that is called) was completely gone. No idea when that had happened, but it was useless. So moving on to necessity number two when traveling : duck tape (or duct tape, again whichever term you prefer, personally I call it "jesari" ("jesus tape"). End result was not pretty but at least it kept stroller and all its parts (wheels primarily) together during return flight.


While duck tape may seem like something you almost never need, it's this kind of situations where it's priceless to have. Just like that string, Leatherman, small flashlight, some spare large plastic bags and now my newest addition to traveling list: paperclips (or some metal wire, but I think I prefer paperclips). (my complete luggage checklist has grown over the years and is now almost 50 items long. Lot of that is stuff that is only needed in some regions and it has also includes passports, tickets, money, clothing, toiletries and so on, so mostly to remind me when packing)

Even more off topic, but it's too bad I didn't take photo of my luggage case some years ago after returning from Berlin - it was so completely destroyed that I was amazed. I still have no idea how they even managed to beat it that badly, it looked like someone had hit it with a large hammer. Repeatedly. Finnair replaced it, (almost) no questions asked, but like with insurance, doing paperwork, dealing with customer service, getting replacements and so on - it all is always such a  hassle.

Oh, and one more thing: No matter where you travel, always - always - have your hotel's business card with you. This I learned in Cambodia when trying to communicate address to toothless, cossack-looking taxi driver late at night. In the end I had to give him directions (with hand gestures) through Phnom Penh (luckily the route was easy), but at least I didn't have to walk.


tiistai 10. kesäkuuta 2014

SLRs and protectors

I love SLR cameras. Whenever I have to use a camera that doesn't give me full "artistic" control, I always - always - end up disappointed ("artistic control" in this control means that I prefer M/Tv/Av modes (as Canon names them) - full manual, manual exposure time or manual aperture). Granted, I have tendency to "tweak" parameters when it not necessarily even needed, but when lighting is difficult those controls are absolutely vital (see recent attempts on LED matrix - granted, it's difficult even with SLR, but completely impossible with usual "point-and-shoot"s).

Some years ago I splurged and bought Canon's EF-S 17-85mm lens with image stabilizer to replace the standard kit lens (18-55mm I think, without stabilizer, I think newer kits come with essentially same lens but stabilizer included but I didn't have one) - the price was about 700-800€. Since then that has become lens I use most of the time.Granted, it's kinda big and heavy, so sometimes it's just easier to use small "point-and-click" type camera -- or even phone.

Since the lens is quite expensive I added "protector" filter on it. If you are not familiar with SLRs let me explain this a bit (I haven't been keeping up with recent progress so it might be that this has come to lower end cameras as well). Lenses typically have threads in front and you can screw in a filter. It can be polarizer (before you ask, no, this really can't be done in post), colorizing filter (this you can do in post so these aren't too popular today), some gradient (say, darkening bright sky, usually quite difficult in post) or whatever. Protectors are kind of filters that are basically just glass - no effect, only very minor loss of light. Most of the the time they are there, doing nothing, but every now and then they will save your day. Say you are receiving end of baseball throw gone awry. Normally ball would shatter your lens and possibly your eye (read: you'll get black eye when camera body hits your face). Protector will take the hit and most likely save your expensive lens, while being destroyed in process. Yay! (you'll still get that black eye from camera body but at least lens is saved!).

They also protect your camera from other unexpected threats. Like toddlers.


This was some time ago when small one was learning to walk. I stupidly had left my camera on (smallish) table and of course he pulled it down. It landed on floor lens-first. Ouch.

The protector took the hit. Glass shattered and metal frame was slightly bent at the point of contact - just enough that I couldn't just screw it off (random scratches you see on that are from pliers, trust me, I tried) but eventually I had to dremel (cut) it off. Very very carefully, of course.

So this is why you want use a lens protector. That 20€ piece of metal and glass took the hit so my 700€ lens could live on. I of course had to get new protector which is screwed on that lens even now, waiting for it's time to shine. I just hope that moment never comes, but you just never know.


lauantai 17. toukokuuta 2014

Printer toner DRM

Some time ago our old printer died - or more exactly, became mostly unusable due to the rollers becoming unable to grab paper from bypass tray. Not long before that I repaired the power board, so that was for nothing but at least bought about a month or so. Replacing rollers might have helped, or some chemical treatments but since I printer was absolutely necessary for normal business operations I couldn't just guess.

So I had to get a new one. Not that big expense, but nevertheless annoying. And of course after only thousand pages or so it started to complain about toner. And now, after few more months it finally refused to print anymore, "change toner cassette". Total to this point was about 2500 pages (I didn't check the counter then and have already printed some amount of pages with new cassette so I can't be exactly sure of the count). Then again, 2500 pages isn't too bad for "starter" cassette these days.

When changing the toner cassette I noticed a small PCB with some pads at one end (printer was delivered to us fully functional so I had no reason to take cassette out before that). Being me - that is, curious (or is that suspicious?), I of course had to take it out, and indeed it was what I suspected - an small PCB with some passives and a small chip on it.


The marking on the chip is "5ME3 R2ES90", and quick search turned out nothing. Not too surprising either, after years of researching random chips one develops kind of "gut feeling" about those markings, and this definitely spelled out "unsearchable" to me.
No matter, when comparing the layout against standard 8-pin I2C EEPROMs it is remarkably similar. So after quick visit on "junk" box I found suitable semi-dead PCB  I could use as base for further exploring (in this context "semi-dead" means that this board was somewhat functional but could not be used in customer devices, even after repairs, so it was put aside for other uses - these typically being some quick prototyping and testing something like this):

The chip visible on main board is a 256kbit EEPROM and there is space for two such chips (sharing common I2C bus) on the board; here the other one was unpopulated so I could solder wires directly there. My guess was that this is small-ish (64, 128 or 256 bytes) I2C EEPROM quick software hack was also needed - I generally use larger (32kB and 64kB) EEPROMS, meaning 16-bit addresses, but dropping hi byte was trivial enough change in C code. And some brief moments later there it is: data dump from the chip itself, all 128 bytes of it:
"T332Q..." part was easiest to decrypt, serial number of the printer as plain text. I just don't like my printer's serial being that readable so it's censored, sorry. No idea however why it is placed in toner memory, maybe every printer the cassette is used in is added there - for what reason I really can't guess.
406972 seems remarkably like a counter, but this printer has done only 2500 pages so the number is a bit high. Also, since these cassettes come in different sizes, I would expect the initial value to be high(ish), decreasing and cassette to be rejected when it reached some low threshold value, so low value would make more sense.

Now, if that 406.. is counter, it would be amount of toner used (instead of raw pages) but I can't really compare it against anything. But then there would have to be cassette type identification somewhere else so printer would know how high value could be which by itself is not that bad idea. However, since printer firmware is practically never updated, no new cassette types could be introduced after first printer was produced - new cassettes need new type ids that need to exist in printer firmware. And in my opinion that is Bad Design.
Another guess for the value would be serial number of cassette, but number doesn't match with anything on the cassette itself, there is only one sticker and it has "MNO" prefix (model number?). That is, unless printer logs lately used cassettes and their print counts, and then just rejects it if cassette "loses" a few prints. But here I may just be paranoid (but then again, that is how I would do it if I had Evil disposition) (off-topic; I have been told that this is actually how modern vehicles (cars, bikes) keep track of the odometer reading - but that is topic for another posting, some time later)

Rest of the data could be anything, your guess is as good as mine. For now I don't even bother to try.

The new cassette is high-capacity one (advertised as 7000+ pages) so I am a bit hesitant on trying to access its chip to compare data, it would suck to make a mistake and lose entire cassette immediately. Maybe later. While I am perfectly aware that it is pretty damn difficult to accidentally write data to chip through I2C I still am hesitating since stupid accidents can and do happen.

Oh, and I did know that inkjet printers use this kinds of chips to track ink usage (this also is why I expected smallish EEPROM, they seem to be commonly used), but so far I had not known laser printers (especially black-and-white ones!) to employ similar idiocy. I know, however, that my next printer very likely will be from some other manufacturer than Ricoh. Just let me use all the toner in the cassette if I want to, damn it.


tiistai 13. toukokuuta 2014

Led matrix update

After some troubles the LED matrix I quickly mentioned before is functional. Unfortunately taking pictures of it (without diffuser, I don't have any handy right now) is damn difficult so the photos aren't exactly of  the greatest quality.




The pictures really don't show observed brightness or color very well, so you have to take my word for it: it looks way better live. And unfortunately my DSLR is one model too old to have video capture, so I can't even give you that (and webcams/phone cams are absolutely worthless - been there, tried that, immediately decided to forget about it)

The four matrices in pictures are chained together and driven by Arduino Uno showing simple color cycle where each component is assigned value with simple rotating sin function, so nothing fancy. Nevertheless it looks quite nice for demonstration purposes (well, when observed live, at least). Arduino manages to update the matrix at rate of 300 updates per second, not bad, and code for updating it is very very simple.

My original idea was that this would be easy-to-use (no complex driving logic required like so many matrices do!) and fairly cheap  module for hobbyist use - showing text, smallish graphics ("We're OPEN!") and whatnot, possibly even slide show from SD card (by using some suitable Arduino shield or maybe Raspberry Pi - neither of which I have available right now). Unfortunately the initial small production run costs about twice what I was aiming for so this may be a bit too expensive (around 70€, including VAT). Damn.
 However, extending this to 16x16 matrix should be fairly simple (granted, routing will be a huge pain, even with added board area) and yet change in cost should be minimal, so maybe I just forget this smaller one and go for that instead.

Any ideas or requests, anyone?


torstai 8. toukokuuta 2014

TV antenna amplifier (another one)

I had this old antenna amplifier ready to be thrown out, but just out of curiosity I decided to open it and see what's inside. Our house was built in early 90s, and according to our neighbors the family that originally lived there was quite religious, in this context meaning that they did not have TV. The area has cable TV but it was never connected to this house. At least the inside wiring was done so connecting TV should be easy later.

Next family living there was ... well, cheap. I've been finding their half-assed fixes (and I'm using the word very liberally here) since moving in, fixing them properly one by one. Even the TV setup was cheap; apparently they bought old antenna, with associated electronics from one neighbor that was updating their system. So this amplifier is likely from the 80s.

Outside there's on/off switch, gain control, indicator LED, one input and two outputs, so quite usual configuration there. The plastic has gotten quite brown and slightly broken from some places.

Assuming that it has usual clips holding it together I tried to pry it open. Whoops. And I didn't even have to use a lots of force.

Right, here's the screw, under the sticker. Finding it first wouldn't have helped anyway, plastic was so badly deteriorated that it would have broken anyway, just from different place.

And the PCB. Top left is on/off switch, below it a fuse (whopping 500mA! Why exactly has someone decided that this thing is allowed to consume 100W is beyond me. Damn thing seems now more like a house fire waiting to happen. Of course I have no way of knowing if the fuse is original or one of those half-assed fixes mentioned earlier), then transformer, on right of it diode bridge and smoothing capacitor. Two round black things with text on them are RF transistors (types BFR 90 and BFR 91A), rest miscellaneous resistors, capacitors and inductors. Nothing too special here.

 So there. Now this thing goes back to trash bin. For good.


perjantai 2. toukokuuta 2014

Teardown of a top-set TV box

Some years ago I signed on Elisa's (local internet/mobile provider) "Viihde" ("Entertainment") service. Original (only) reason for signing up was ADSL (originally 20/1M) but it also includes Tivo-like functionality (by connecting to their servers, you are given about 4TB of (virtual) space for recordings) and on-demand movie rental (also in 1080p) by using their custom top-set box. Total is about 40€/month, not bad (rentals on top of that, if used).

When I signed on I still had my old Topfield box which was quite sufficient, but it finally broke (actually it became unreliable - HD wouldn't wake up sometimes. I still have it but don't really know what to do with it, aside throwing it away - I did examine it but couldn't find the culprit for problems) so I moved on using Elisa's box and was actually quite surprised. I didn't suck - not too much at least.

Unfortunately the TV reception of the original box had grows progressively worse over the time, so I had it replaced with newer model. No need to return the old one so of course I had to take the old one apart to see what's inside. Unfortunately it was pretty much what I expected - system-on-chip solution with minimal external parts.

Here's the board (warning, large image).


The main processor is as expected, "SMP8635LF Secure Media Processor". I couldn't find a datasheet with quick search so I'd expect it to be under NDA. No matter, it isn't too difficult to guess that it contains relatively secure boot loader and loading (possibly encrypted) software from external flash (chip below it, sticker on top) and possibly also encryption of external memory contents (four chips up and right from it). Most likely some tampering detection thrown in for good measure. From system design perspective the datasheet might provide interesting read though.

Lower left corner (highlighted in red) is a bit more interesting. Larger chip is STM32F family MCU , but smaller one is NRF24L01 - "Ultra low power 2.4GHz RF Transceiver". This is not WLAN chip, it can only transmit relatively small data frames, so my guess would be an RF remote control or possibly programming the customer-specific parameters to the unit (each unit is tied to your account and since my account is now moved to new unit, this one will only report error when trying to connect to server). Provided remote was typical IR-based one so if they had RF capability it wasn't used. Pity, I'd love to hide this kind of units that don't need physical access behind TV or other such place where it wouldn't take real estate from units that need to be accessible (like DVD player).

The smaller red square highlight another mildly interesting part of the board. This actually appears to be USB connector. Since this is not available from outside and traces go directly to the main processor, this might be the production programming interface (there is distinctly JTAG-looking header on the bottom of the board, though)

The USB connector right from there is accessible from outside, but it can only be used for time shifting live TV (as in pausing program). There is another USB connector at back of the board too. I think I never used either of those.

On the other (bottom) side there is usual load of passives (resistors and bypass caps for chips), and a card reader module with interface chip. The is also a card interface, accessible through a slot in bottom of the (fully assembled) unit. Box has ability to subscribe to paid channels through your account IPTV so it doesn't really need card, but still it could be useful for accessing usual OTA channels, say, if your fried brings his card over.

Empty footprints at left from the processor and empty connectors look interesting too. Possibly SATA interface for optional internal hard drive? (and other large empty place - PATA connector? I don't  recognize any of those footprint patterns definitely so these are just educated guesses)

At the upper part there are connectors. TV in and out (with associated RF stuff, here with can cover removed), HDMI, another video connector (looks kinda like S-Video but has 9 pins, some non-standard connector?), headphone, optical out, another USB, Ethernet and power, each with their associated interface electronics. And on right power supplies (chip in middle has markings "Summit 113 1085LA1033" - again quick search finds nothing, but my guess is some kind power management controller).

So, all in all, this is another demonstration of current trend of electronics design. Single-purpose unit with any ability to hack or repair it very carefully removed (granted, I kinda understand it in this case, being able to receive and show HD content over internet). But that seems to be the direction we're going now. Doesn't mean that I have to be happy about it though.


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...