Saturday, November 21, 2009

Well

I have a new reality to adapt to, lack of sleep - I work 2 jobs now, 11pm-7am, then my old job where there is a promise to pay but intermittent pay from 8 to 1230.. got paid last Friday for two weeks there, which made a whole lot of difference when you are in an income to bills is almost even pinch, anything above normal income makes a huge difference. Otherwise I never get out of debt. Of course I'm always on the lookout on how to cut cost too, to break that income to expense ratio into something with more freedom, and part of the reason for currently having such a pinch is the promise later there'd be more freedom. Or the illusion of a promise. Anyway, the first few days at my new job I was still thinking about this stuff, microcontrollers, but mostly off my mind lately, for practical reasons. I have to sort of let my mind be blank and not wander off on the deep end and mess up at work hard. Instead I've become a farmville addict on facebook, to take me into the next year if everything goes right, and once I pick up and get all used to the job, I can start pondering things off on the deeper end again. I haven't written here for a while.. the following are gonna be just jotted down notes of what I remember thinking, without full explanation. Lack of full explanation also means you don't know something well, because you don't know something thoroughly until you can teach it or explain it to death. So I'm not learning as well as I could either. So I was gonna write that of course the factoradic is not more terse than the positional arabic/indian. For any selected base, you might as well go all the way up to the base in each placeholder and not stop halfway there, and if you're past the base, the diff notations are equivalent - hex vs binary, hex digits being a summary of 4 binary, one can go arbitrarily high on the base if ultimately it has to be hardware represented in binary, a high base is equivalent to binary. But this gets one thinking on the right path of how to find more terse ways. Terser notation, even if the mechanics are very complicated - such as mechanics of addition of positional is more complicated than tally, but still well worth it. Mechanics and sofistication are cheap, storage is expensive. Look at life - complexity and sophistication is cheap, food and energy is expensive, and even something very complex, such as a shark, might die from simple lack of food. So for numbers, we can look at how notation evolved over time - simple additive tally stick, then special symbols such as roman numerals, for multiples of tally sticks, then raising to the power positional system where the special multiple is understood in the position and extensible to infinity, the power being multiple multiples. That is, multiplication comes about from repeated addition of the same thing, 2+2+2+2+2 we call it 2x5, raising to power comes about from repeated multiplication of the same thing, 2x2x2x2x2=2^5, so the next logical step would be 2^2^2^2^2=2something5, repeated raising to the power of the same thing. It's a way to succinctly represent very large numbers. But that in itself is not enough. Just as floating point representation has many holes in it, but very succinct for very large numbers, n^n^n has holes in it, lacking granularity, and representation of each integer in between the gaps. Basically we need a representation that can do an n and n+1 easily no matter how large the numbers. The arabic/indian positional system is great, because the sum of geometric progression, for example 9x10^0+9x10^1+9x10^2+9x10^3=10^4-1, has a neat formula for the next introduced expansion in notation requiring one further symbol being the sum of all the other symbols -1, so adding the one clears all the others and expands the notation. Same with factoradic, 5!-1=4x4!+3x3!+2x2!+1x1!+0x0!. Basically all the other notation digits get reset to 0 as the new expansion symbol is introduced into the notation. Of course there are other number systems, such as the roman, which are not positional (or weakly so). In roman the symbols are just piled on, each new expansion requiring inventing a new symbol, and the notation is not terser than the positional, except for numbers very close to the invented symbol. That nonuniformity may be an advantage in certain situations. I've come across over some posts by Golovchenko, where multiplying by every single constant up to 8 is optimized.. still have to read through it, can't find the page right now. Basically if you have a number very close to say 2^2^2^2...^2, then it can be represented more tersely and possibly with fewer cpu cycles. But complexity in execution is not at stake here, if we can find a more efficient way of storing numbers in a minimum amount of space and representation, that takes precedence, but for equal storage density, of course lower complexity or fewer operations is better, even if it only happens in special cases.
So is there a full granularity integer representation between the geometric series representation, with no holes of granularity, and between the speed of n^n type representation that's too fast, and loses granularity per bit? Finding such a thing would be a nice leap forward. Even the maya had a positional system with mixed bases.

Sunday, October 18, 2009

Musings

Since the resources and space are so limited on the PIC, one always has to think of clever ways to squeeze out more from very little. For instance, on the PIC 16F84 memory, or working RAM is limited to 80 bytes. 3(for 2s/20MHz) to 6(for 1y/20MHz) of those were used up in the previous code simply to implement a delay. We needed to use 6 variables of 256, because (2*6+1)*256*256*256.. 6times=15*256^6 is what's able to execute the needed amount of instructions for 1 year. 256 is the biggest number we can represent in the PIC with a single memory location.
I was thinking perhaps there were a way to get away with less variables, to make big numbers. After all, if I'm given two bytes, d1 and d2, each able to store 256, my options are 256+256, or 256*256, or.. or.. how about 256^256.. now that's a huge number. Even 256^8 is huge. So is there a way to get aways with say d1 storing 255, and d2 say 8? What's the mechanics under the hood, can we generate the huge number of operations needed for a delay with just these two register? In C one would just make a routine,
pow(int x, int y) {int i, result=1; for(i=0;i!=y;i++) result=result*x; return result;}

Well, here is where C programmers or high level programmers think abstractly, and forget about the underlying architecture, and expect things to just work out. In practice however, first of all, this function results in overflows pretty fast, because a power such as 10000^10000 is not going to fit in an int result variable. The very reason C has datatypes is to enable efficient use of memory, and for the programmer to keep in mind the limits and the architecture at hand. VB does not require type declarations, and anything undeclared ends up as a 16 byte Variant type. Note the even the biggest long long int, on C is only 12 bytes. Still, 16 bytes is not enough for everything, because it can overflow too. Abstraction makes it possible to write code independent of the architecture and the hardware that it runs on, but eventually it does come down to having limits, PC computer hardware is not unlimited, at least not like it used to be back in the days when IBM made the decision that 1 MB should be enough memory for everyone. That decision has been laughed at ever since. Note that in the picdelay.c program below, I made a similar decision that 1 year should be enough for anyone, in view of the architecture. In the end that 1MB decision turned out to be very wrong, and since then, we learned our lessons very well, and proper new design tries to eliminate any built in limits. For instance in the old 8086 DOS PC, working memory was up to 640 KB, and above that was the video memory, and other things, up to 1MB. When practical memory limits grew to 8 MB with the 80286, the computer had to keep running circles around that video memory, and load contiguous blocks of memory from above 1MB to the block of 0-640 KB, work work work with it til it ran out of stuff to do, and then it had to take everything and move it back above 1MB, and load a new work dose from 1MB-8MB region to the 0-640KB region. In fact some device drivers loaded, such as CD ROM drivers or mouse or joystick drivers, required a few KB's of memory, and you ended up with 600KB or 586 KB or even less "conventional" memory, which was not enough for a lot of games to run, which needed at least say 604KB contiguous to function. You had the option to not run the CD ROM device driver, that could save some memory, or there were some memory optimizers like QEMM, that sought out contiguous empty space that was not used by any hardware between 640 and 1MB, and loaded CDROM drivers there. They would stay resident, but this way you could squeeze 629 KB! of working RAM, AND have a gazillion device drivers still loaded "high." Had they designed DOS without this fixed location limitation, such as the video memory address start location shown by a pointer value stored somewhere, things might have been easier to adapt as technology advanced. But once you had to adapt to the status quo, and stay compatible, it was hard to change things. One option of course is to require each computer to come with 8MB and a newer design spec says video memory now is between 7.64 to 8.00 MB. Any old program written assuming 0-1 MB design would have to be rewritten. That would be a mess.
Win32 has a flat memory model, and any program written is given a sandbox where it thinks it has access to all the memory on the computer, and Windows does the translation of what a program memory of say 0 memory location, or 1MB memory location translates to in the real computer, which might be the 12.5MB to 13.5 MB region. This way you don't have to rewrite windows programs to adapt to the new limits.
So back to 256^256 - can you implement code with only 2 registers and do this many iterations, find a cleverer way than having to use 6 registers? Would this be more elegant, maybe use even less instructions? Well, the answer is no. I actually tried. What happens is that you need a way to represent and store the intermediate numbers. In order to raise to power, you need to multiply, and in order to multiply, you need to add. In the PIC you have to add manually to multiply, and then use this multiply to raise to power, manually. Things such as 3^3 =27 or 4^4=256 fit into a register, but anything bigger doesn't. You could try to consume up the so far stored stuff before you do a next step, so before you come and multiply again, how about doing the iterations now, one by one, instead of doing them later. This does not work, because the very essence of raising to power, such as 256*(current product of previous 256*256..) = 256*123456789012=12345679012+12345689012+.. 256 times. Should you use up any of these intermediate values, you won't have the huge numbers to add up on the next turn of multiplying with 256.. basically +/- is one operation step away from * multiplication, but ^ raising to the power is 2 steps away, there is no quick and dirty method to decrement in between so you don't get an overflow while raising to power. So you can't do raising to power, unless you're willing to store huge intermediate values. You can make your own custom type, and dedicate 16 or more bytes to storing the values in it, but that negates the whole purpose of trying to save registers in the first place - use 16 registers to save 7 registers, and make the code very complicated too, similar to old 32 bit Windows on 16 bit PC architecture such as a 286 - low byte, high byte, what a mess that was. Linux was started out later, and by design it does not run on anything less than a 386, which is natively 32 bit, simply to not have to deal with low byte, high byte mess for internal calculations of memory addressing.
Basically the below delay code, using as many registers as needed and going with the 256*256*256*256... way to generate large numbers, is the most elegant and efficient way I can think of. In the mechanics, the intermediate values needing to be stored are never greater than 256, and can be decremented along the way, while the multiplication happens, so you don't need to first generate the product, then start 1 at a time from a huge number, but you can take one of them, decrement it all the way, then continue with the multiplication, and the final result of how many instructions were ultimately done, is not affected. Using registers + is not as efficient as * to create large numbers, and ^ is unimplementable without storing large intermediate values greater than 256, so it's not more elegant. Unless you can think of something I didn't think of.
By the way, while surfing around for answers on this topic, I came across the factoradic number system, which is a mixed radix number system (it's not 2 base like binary, or 10 base like decimal, or 16 base like hex, but each digit has its own base, the prior factorial up to that point. Because factorial is roughly proportional to N^N, huge numbers can be stored with few digits after a certain threshhold. The factoradic number system is basically the next step beyond arabic numeral notation - the + is tally marks fast, the arabic numeral system is developing * to its finesse with a fixed radix, and the factoradic gives a notation ^ fast. I'm not smart enough a mathematician to really analyze this, but there might be ways to implement factoradic in hardware that could give more efficient computation, at least when the number of digits stored is huge, probably well beyond 64 bit. Instead of the highest number stored being around say 2^64, one might be able to get closer to 64^64 magnitude number with accurate individual step granularity squished into 64 bits.

Made my own offline picdelay calculator

I made my offline version of www.golovchenko.org/cgi-bin/delay
that should work for up to 1 year delay on a PIC which should
be enough for ordinary people. If you don't like it, you can change
the source! There is a discrepancy on 31536000 seconds output,
and I contacted the original author.
It mostly works the same, especially on small numbers, but on one year
delay his page gets d1 as 0x4D, me, I get 0x4E.
Also, the final cycles he needs 8+4, I need 6+4.
When I do the hand calculations with his numbers, the number of inner
cycles is 157679999999977 instead of 157679999999988 that his page states.



/* picdelay.c
usage: gcc picdelay.c; ./a.out
Generates source code for delay up to 1 year on <20MHz PIC ucontrollers
Mimics output of www.golovchenko.org/cgi-bin/delay

License: Public Domain by me,
the Anonymous Author@kolomp.blogspot.com
No contact info, so I don't get bothered with spam.
Hope you enjoy it.
*/


#include <stdio.h>

int main(void) {

long double mhz, delay_s, act_delay_s;
unsigned long long int totalcycles, ncycles, dummy;
unsigned char d[8], i, nvars;
//d[8], 256^8 > 365*24*60*60 secs * 20 MHz/4 cycles, max prog limit
//needs to be changed for longer delays/faster chips

printf("Delay seconds: "); scanf ("%Lf", &delay_s);
printf("Clock MHz: "); scanf ("%Lf", &mhz);

totalcycles=1e6/4*mhz*delay_s;
act_delay_s = (long double)totalcycles/mhz*4/1e6;

ncycles=totalcycles-4-1; //to include for "call" and last goto instructions

nvars=0; dummy=1;
while(dummy<ncycles)
{ nvars++; dummy = dummy*256*(2*nvars+1)/(2*nvars-1);}
//number of repeated instruction lines 2*nvars+1
//printf("dummy=%llu\n", dummy);

for(i=nvars;i>0;i--)
{ dummy = dummy/256;
d[i]=ncycles/dummy;
ncycles = ncycles % dummy;
//if (i>1)
// printf("d%d = 0x%X\n", i, d[i]+1);
//else
// printf("d%d = 0x%X\n", i, d[i] );
}
//ncycles left over, ex. on a 7 instruction loop the remainder could be 0,1,2,3,4,5,6
//add the 1 that the last goto misses
ncycles++;
//printf("ncycles=%d", ncycles);


//printf(" Delay seconds: %Lf seconds\n", delay_s);
//printf(" Clock frequency: %Lf MHz\n", mhz);
printf("; Actual delay = %.16Lf seconds %llu cycles\n", act_delay_s, totalcycles);
printf("; Error = %.16LF % \n", (1-act_delay_s/delay_s)*100);
printf("\n");
printf(" cblock\n");
for (i=1;i<nvars+1;i++)
printf(" d%d\n",i);
printf(" endc\n");
printf("\n");
printf("Delay\n");
printf(" ;%llu cycles\n",totalcycles-4-ncycles);
printf(" movlw 0x%X\n", d[1]);
printf(" movwf d1\n");
for (i=2;i<nvars+1;i++)
{ printf(" movlw 0x%X\n", d[i]+1);
printf(" movwf d%d\n",i);
}
printf("Delay_0\n");
for (i=1;i<nvars;i++)
{ printf(" decfsz d%d, f\n",i);
printf(" goto $+2\n");
}
printf(" decfsz d%d, f\n", nvars);
printf(" goto Delay_0\n");
printf("\n");
printf(" ;%d cycles\n", ncycles);
for (;ncycles>1;ncycles=ncycles-2)
printf(" goto $+1\n");
if (ncycles>0)
printf (" nop\n");
printf("\n");
printf(" ;4 cycles (including call)\n");
printf(" retlw 0; \n");

return 0;
}

Thursday, October 15, 2009

Accurate PIC Delays

Time to learn PIC's all over again.
This entry is written very rough draft jotting down notes style and I apologize for the style.

I have PIC-PG4D from Olimex/Spark Fun Electronics. Spark Fun no longer calls it PG4D, and it's not listed under the PIC programmer section, but they still sell it for $27.95 under the sku: DEV-00001 in development tools http://www.sparkfun.com/commerce/product_info.php?products_id=1, called Development Board with Onboard Programmer. I think this is by far the best value to get started with PICs even today, compared to USB programmers.

It's a serial JDM-type programmer, and because it's JDM-alike, many generic PIC programming software tools work with it. My favorite programmer software is the command line "picprog" listed at http://hyvatti.iki.fi/~jaakko/pic/picprog.html. I use any old text editor to edit the assembler code, and gpasm to compile the hex file that can be burned onto the chip via the programmer.

I used to have a parallel port programmer, but the parallel port has disappeared from today's laptops, and they only come with USB ports anymore. USB to parallel port converters don't work for pic programming. Seriously, just don't bother. There is someone who sells custom USB2LPT parallel converters, but even he says that with each IN instruction the USB frame must be waited on for 125 us, and this can increase a pic programming time 100x times. So if it took to program a chip under a second via a conventional parallel port programmer, it may take over a minute to accomplish the same thing via one of these converters, if they only worked at all. Just don't bother. Unless you have a PCMCIA slot, or a desktop computer with a free PCI slot, each of which accept regular fast parallel port adapters, so if your only option is USB, then a parallel port programmer is out of question, and you can only use USB or USB/serial adapters.
USB adapters are becoming the norm, but for starting out and really learning the guts of what's going on, the serial port is still the best option. Unfortunately most USB/serial converters don't provide the classical -12V/+12V sufficient voltage to program a chip, but they most likely to go 0 to 5 V, or something intermediate between 5V and 12V, such as 8 V, which still works well enough with most serial port communication functions. Luckily I bought a Belkin F5U216 USB Dock station for like $20 or so back in 2004 at Best Buy. It's a really clumsy device, with a useless VGA passthrough cable that adds to the cable mess you have to drag around with the laptop, but it does have its own separate power adaptor, and it seems to supply enough voltage to program a PIC. It's an FTDI chip based device, and another less clumsy dock station that's PL2303 based, I had no luck with as far as programming voltage goes. Your luck may vary with these USB to serial adapters, and may have to go through quite a few til you find one that's able to program chips via USB/serial JDM adapters. But ultimately it may be worth the effort. The alternative of buying a separate USB programmer, and then using a regular low voltage USB/serial adapter to talk to the chip may be in the end cheaper, but it requires moving the chip from socket to socket, and the pins may be bent and broken off. Another option, of course, is to directly supply the programming voltage, and use a transistor to switch it based on the low voltage it gets from the serial port. But this you have to make yourself, and can't buy a kit that's ready made, and guaranteed to work. I wonder why olimex/kitsrus and the rest don't sell serial programmers that either work just off the serial port, or have an option to connect a high voltage source in case the serial port doesn't provide it. After all, internally, the USB based programmers also use a USB/serial converter. Having just a serial programmer, and a separate USB/serial adapter frees up the USB/serial adapter for other uses too. The picprog author says that USB to serial adapaters will work slowly, because the serial control lines need to be toggled, and each of those operations takes milliseconds, and a full programming of a chip up to an hour. But my Belkin F5U216 USB/serial dock station programs a PIC16F628A in like 3 to 5 seconds.

Once you have a programmer, you can solder many fun circuits you can find all over the web. The classic chip is PIC16F84A, which is what most classic tutorials and circuits are about. It's a very good midpoint of the spectrum to dive in at, to start out learning, but eventually you'd move on to the newer and cheaper pics, or either the lower performance 10F/12F series, or the higher performance 18F series. Actually the cheaper 16F628 is equivalent to 16F84 if the comparator registers are turned off, and it's recommended.

Microchip has all the datasheets you need, and they are extremely well documented. Currently, Allied Electronics, with a minimum order amount of $30, sells PIC's very cheaply: search for Pic, then limit the search to I/P so you don't get surface mount SOIC's. PIC10F200 is $0.46, PIC12F683 $1.18, PIC16F54 $0.55, PIC16F628A $1.73, PIC16F88 is $2.60, and they no longer sell the PIC16F84A, even though last week they still did. Out of the above bunch the PIC16F628A is recommended to start, and should be supported by most programmers and software you can find around the net. The PIC16F88 is the candy/king of the bunch, and still sufficiently F84-like to get started with.

The best starting point for absolute beginners, and programmers who've never seen assembler programming in their life, is http://www.mstracey.btinternet.co.uk/pictutorial/picmain.htm. It's PIC16F84 based, but it's directly applicable to the 628A, so don't worry.


One of the benefits of PIC programming is accurate timing on the microsecond scale. While in the past one could use the IBM PC with MSDOS directly to control external devices through the parallel port, these days, most modern multitasking operating systems no longer allow accurate timing, and delays/hiccups of CPU availability on the order of 250 milliseconds or more should be considered. If your application needs to log something once an hour or so, that is more than sufficient, but if you need exact timing, such as talking to a DS18B20 thermometer, or a HD44780 LCD, direct PC control is almost out of reach. I remember in 2006 I was requested to create a software slowly ramping up voltage on a power supply, from 0 to 300V, to coat some electrocoated panels. With the timers provided by the windows API the fastest delay time was 20 ms inside windows NT, with unpredictable occasional hiccups of over 200 ms. When the ramp time is 15 seconds, a half a second hiccup near 80V along the ramp may or may not significantly affect the reproducibility of the test. Running on top of a nonrealtime OS, where the OS may capriciously decide to churn some harddrive, or dump some memory cache, or attempt a network connect timeout in the middle of what you're doing, that's an iffy situation. This nonrealtime preemptive issue keeps the computer from direct automation and control of things such as a nuclear power plant or a submarine, and direct control and accurate timing is handed off instead to dedicated chips, such as a sound chip, or a serial UART, etc. Hence the need for the PIC, and learning how to program it. If you want to control motors, chips, any kind of devices, and you want to make good scientific measurements, you can use a PIC as either a standalone computer with no harddrive or keyboard or display, or a PIC connected via a serial port to a PC, where the PIC is your accurate realtime buffer between the moody and unpredictable, and mysterious computer OS and the real world. I don't even know what programs are running on windows anymore, since many of them can be hidden even from the task manager. At the Linux command prompt only ps ax or top lists most running tasks, and it feels more secure, even if Linux is generally under very heavy sabotage, at least there is no hidden direct spy features built into it, because the sourcecode is available for inspection, unless gcc inserts something, but that sourcecode is available for inspection too. Also, under a network connected windows computer MS has direct access to it, and can any time piss in your cereal, when you want to make a real world measurement, execute a remote procedure call on you. If you shut down the rpc service on NT, a countdown messagebox starts and automatically reboots the computer. That's a big no no. RPC has to run at all times. If you don't like it, what else you gonna do? Go to a competitor? Good luck finding one. Running and isolated windows session may not be possible in a few years. This is also where the PIC's are a refuge, since they are meant to function standalone, no keyboard/monitor/harddisk/memory, just a nanowatt battery, and possibly a 3.5 mm earphone plug serial connection, or an RF/serial connection, or maybe a set of LED's or even an LCD. Oh what freedom it is. Slow, can't do much in it, but at least no bullshit, because what you can do, you can rely on. And redundancy is cheap.
Imagine making your own garage openers, temperature monitors, or even home security systems. Automating your world a' la Jetson style. The PIC's make it affordable. As long as there is a roughly equivalent competition, such as coming from the arduino AVR microcontrollers, or even the intel 8051, prices, affordability, andproper, customer focused market behavior should be naturally happening. If any one gets too successful and leaves the others behind or forces them completely out of business, the market could turn into a monopolistic nightmare.

So here I am trying to learn PIC's again. Every time I try, Da Man uproots me and gets me out on the street, without a roof over my head. I'll never learn.

As you start out learning PIC's, the very first things you'll do is flash an LED. Set up the input/output ports, and change the bit values on them on and off. Of course a PIC running at 20 MHz gets an instruction execution time of 0.2 microseconds, and that's too fast to see for the human eye, so you have to learn delays.
Since you're working at very low level, only byte numbers up to 255 are available, and any numbers such as 10 million have to be expressed/manipulated via such small values. Subtracting 1 from 0 rolls over to 255 in a byte, and adding 1 to 255 rolls over to 0, with the carry flag bits set. It seems like such a bother compared to modern C compilers, but what you get in exchange is knowing exactly what happens on the CPU, no mystery about it. The possibility of a virus infection brought to you by the compiler is nil, because you can decompile and examine each and every cpu instruction, and understand what it does exactly. Secure computing. It's only possible on very small scale, with very low complexity systems, but that's where everything starts, before scaling up. Talking about being a computer security expert without understanding assembly is ridiculous. I never had the chance to learn assembly before, I'm pretty fluent in BASIC, Pascal and C and from here of course in most similar high level languages like javascript/java/C++/python, but assembler has always been a mystery to me. There is always a chance that the c compiler is rigged, and unless you're able, at least in theory, to personally examine the compiler output, you can never be sure about your computer's security. Though the price is dear, another benefit of assembler programming is that you're able to use hardware directly without trespassing and violating someone else's copyright and intellectual property. You can write your own OS or your own compiler, if you wish. It used to be that computer scientists all knew the inner functionings of computers, and they were all able to program assembler. They didn't do so because of the benefits and ease that high level programming tools provided, but they understood what these tools ultimately did, and were able to create high performance and quality software, if necessary, dropping back to assembler and directly working with the hardware. That was true computer science. Today's programmers coming from diploma degree mills are slaves to the tools they are given. If these tools suck in performance, anything they create with them sucks. They don't know how to create better tools. They are told they are forbidden to even try to understand how a tool works, because that would involve reverse engineering. Eventually only an elite, a select few special circle of people will be allowed to program with high performance, directly on the hardware, and everyone else mandated to use the high level and expensive and remotely monitored tools, because otherwise it will be a trespass on fully locked down and perpetual patent rights. Only an elite select few people will have access to the patent rights, especially when patents will be set to never expire, or renewable ad infinitum. It's called a competitive advantage in the name of self interest. Only special people will be allowed to write high performance code, everyone else will have to live and run on top of artificially sabotaged and held back tools. We can even see that today, java and dotnet seem very much like that. Hence Vista sucks. DOS, with a parallel port, and Quake, used to rock. It blew the minds of their users with the hotrod speed.
In today's world being mandated to use developer tools forced onto users by monopolies feels like a forced religious conversion, a violation of the First Amendment of the Constitution. Moreover, the backdoors put into network connected computers, and the constant remote watchful eye of the proprietary system holder making sure no wrong clicks and no intellectual property violations are happening, intruding into the user's private homes through network wires, seems like a violation of the Fourth Amendment of the constitution. All the while viruses and hackers have no problems trespassing also, and in fact, they are used to further scare and intimidate end users into blindly obeying a centralized high command. Nazi style. These trespasses on individual freedoms are happening in an effort of self interest, as a power grub and control, by those doing them. End users are no longer in charge of their own lives, or their own destinies, at least as far as computing destinies are concerned. What can you do in view of all of this? Well you can use Linux, but that too is so bloated anymore and under such heavy sabotage anymore, (compare Knoppix 3.4 to 6.0, wonder if Klaus is still alive, and it's not just an imposter releasing newer versions acting like its him), that that too is no safe haven. PIC's are a safe haven in the sense that they are so small, there is no room to even run and OS, or do anything really complicated to deceive the user. It's just you against the bare cpu, and you can still get some very neat, exciting and useful things accomplished with it. Artificial intelligence is impossible with them, in view of the very limited resources and speeds available, at least compared to today's supercomputer simulators. The bang per buck, the risk of artificial intelligence development vs. the benefit of usefulness they provide is very high. And security is a given, and redudancy is cheap. In fact microcontrollers could safely run and automate nuclear power plants, space stations, cars, etc, with generally available and small learning curve skills by the whole population. Another world war, or nuclear holocaust, and the remnants of technology such as complex computers, would be unusable by Joe Schmoe, but a microcontroller could be, and rebuilding a world could be accelerated. If a space station fails, and 3 astronauts are stuck on it, they are simply unable to take care of things for themselves, and fix them, unless, of course, everything is easy to fix, everything is running on top of things they understand, such as microcontrollers. I come from a chemical manufacturing/science background, where proper measurement, and time, are very important, if nothing else, for safety reasons. PLCs and ladder logic fulfill these functions today, but cost wise, PLC's and PICs are a different ballpark, and tenfold redundancy is similarly cost prohibitive with them, unlike with PIC's. Automation can eliminate tremendous amount of backbreaking work, and make the word a more efficient, easier and safer place to live in. Microcontrollers seem like a Godsend in this regard. If one can only learn them. I'm not sure I'm smart enough to, in a sense, to learn everything, to "take charge of my destiny," and learn how to fix the things that can be fixed in my life around me, or improve the things that can be improved, but at least I can have a go at it, I can try. But I wandered off a bit from the topic.. back to Delays.

One of the most beautiful PIC instructions is the "nop", no operation. You never encounter it in any high level programming language where things are obfuscated and uncertain, but where ever you see it, it's a comfoting sign that things are running under full accountability of time. After all besides his own programmer's time and pay, a main resource a computer scientist has to budget is execution time of software, the other limit being memory. These three things have to be held in balance - programmer time, execution time, memory consumption. These days everything is focused on programmer time, with grave sacrifices on execution and memory. And this would be all well, since even today, it is the programmer time that's the only expense. However as programmed devices are becoming ubiquitous, and energy consumption important, the nanowatt power PIC's with low memory resources will be more than adequate for many functions. Such as Roomba's. But I'm drifting off topic again. Back to delays..

Listing of ledblink.asm:
;Tutorial 1.2 - Nigel Goodwin 2002 - initial template
;modified by me, author at kolomp.blogspot.net

LIST p=16F628 ;tell assembler what chip we are using
include "p16f628.inc" ;include the defaults for the chip
; processor p16f628
; __config 0x3D09 ;sets the configuration settings (oscillator type etc.)

cblock 0x20 ;start of general purpose registers
d1 ;used in delay routine
d2 ;used in delay routine
d3 ;used in delay routine
endc

org 0x0000 ;org sets the origin, 0x0000 for the 16F628,
;this is where the program starts running
movlw 0x07
movwf CMCON ;turn comparators off (make it like a 16F84)

bsf STATUS, RP0 ;select bank 1
movlw b'00000000' ;set PortB all outputs
movwf TRISB
movwf TRISA ;set PortA all outputs
bcf STATUS, RP0 ;select bank 0

Loop
movlw 0xff
movwf PORTA ;set all bits on
movwf PORTB
nop ;the nop's make up the time taken by the goto
nop
call Delay2s ;this waits for a while!


movlw 0x00
movwf PORTA
movwf PORTB ;set all bits off
call Delay50ms
goto Loop ;go back and do it again

; Delay = 0.05 seconds
; Clock frequency = 20 MHz
; Actual delay = 0.05 seconds = 250000 cycles
; Error = 0 %

Delay50ms ;249993 cycles
movlw 0x4E
movwf d1
movlw 0xC4
movwf d2
Dly50ms_0
decfsz d1, f
goto $+2
decfsz d2, f
goto Dly50ms_0
;3 cycles
goto $+1
nop
;4 cycles (including call)
retlw 0x00


; Delay = 2 seconds
; Clock frequency = 20 MHz

; Actual delay = 2 seconds = 10,000,000 cycles
; Error = 0 %

Delay2s ;9999995 cycles
movlw 0x5A ;90
movwf d1
movlw 0xCD ;205
movwf d2
movlw 0x16 ;22
movwf d3 ;6 cycles so far

Dly2s_0 decfsz d1, f ;first trip to zero: 90*7=630 cycles, 90th activates d2 to 204
goto $+2 ;subsequent trips to zero 7*256 (from 0-1=255 rollover, i.e 256-1)
decfsz d2, f ;first trip to zero activated by d1->0 to 204, total 204*256*7+90*7
goto $+2 ;subsquent trips to zero total 256*256*7
decfsz d3, f ;first trip to zero only trip to zero, activated by d2->0
goto Dly2s_0 ;total 21*256*256*7+204*256*7+90*7=9999990-1 cycles
;-1 comes from the final decfsz d3 skipping a goto

nop ;1 cycle
retlw 0x00 ;4 cycles (including call)

end


I hope you just scrolled through that and continue reading here. I apologize for the indentation. but the pre preformatted tag is not obeyed in this blog, and I keep losing the tabspaces. You might best off copying and pasting it into a text editor and hand formatting the comments and indentations. I basically went and followed the tutorial at http://www.winpicprog.co.uk/pic_tutorial.htm
and modified it to work for the PG4D I have. Had to change the config bits from 0x3D18 to 0x3D09 (by using Kcalc's scientific feature to convert between hex and binary and the 16f628's datasheet pdf) to update to external 20 MHz oscillator, as opposed to the 8 MHz internal oscillator the tutorial uses. The delay routines I used to scratch my head at, until I found the source code generator at http://www.golovchenko.org/cgi-bin/delay

The above sourcecode when compiled with
gpasm ledblink.asm
at a command prompt, outputs a ledblink.hex file, that looks like this
:020000040000FA
:1000000007309F0083160030860085008312FF3082
:1000100085008600000000001D200030850086005D
:10002000122007284E30A000C430A100A00B1928D0
:10003000A10B16281B28000000345A30A000CD3038
:10004000A1001630A200A00B2628A10B2828A20B85
:060050002328000000342B
:00000001FF
This hex file, containing machine instructions only with sourcecode comments stripped, can be directly burned onto a pic, or disassembled with gpdasm, but the decompiled stuff looks pretty haywire. There is nothing like the original sourcecode, full of comments, and full of the choice of variable notations of the original author.
To burn the hex file onto the pic, my Belkin F5U shows up as /dev/ttyUSB0, so, after flipping the switch on the DEV-00001, and disconnecting the power source, I burn it with the command
picprog --burn --device=pic16f628 -i ./ledblink.hex --jdm --pic-serial-port=/dev/ttyUSB0
The very bottom subroutine, Delay2s, is where I tried to understand how it works. The neat thing on a pic is that you can count time by simply counting the lines of instruction. To reiterate, each instruction in a PIC takes 4 clock cycles. A 4 MHz crystal gives 1us instruction time, and a 20MHz crystal, the one that comes with the DEV-00001 from Spark Fun, a 0.2 us instruction time. For a 2 second delay, we need 10 million instructions executed before proceeding to turn the LED back on.

At the delay2s label, that serves as a marker for a future goto instruction to come to, we start following the execution of instructions. movlw means move literal value to w. W is the working register, and the PIC is retardedly simplistic on having a single working register. Have I said PIC's also follow harvard architecture, as opposed to von Neumann, where code and data space are shared? This feature makes it even more secure, since buffer overflows of data don't turn into instructions. Though there are ways to circumvent such things and make data as if it were an instruction, at least it's a first line defense, an extra safety barrier.
Once the W register is filled with 0x5A hexadecimal number, (which, using Kcalc, turns out to be 90 decimal, or 1011010 binary), the next step is movwf d1, meaning move contents of the W working register to file d1. d1 was set up at the beginning of the source code to mean memory location byte register 20 (d2 is 21, and d3 is 22) (that you can find on the datasheet of the PIC16F628A), each of these d# values being able to hold a byte, or a value from 0 to 255. Since we're trying to iterate 10 million times, 256 is not enough, 256x256=65536 is not enough either, but 256*256*256=16,777,216 is enough to represent 10,000,000, so we need 3 bytes memory. The three values of 90, 205 and 22 were obtained by http://www.golovchenko.org/cgi-bin/delay

and the verification of how they work is explained in the comments below.
Once the 3 initial values are setup in the registers, we proceed. The next instruction, decfsz, meaning decrement file and skip if zero, is a branching, conditional instruction, similar to if..then constructs in high level languages. It takes 1 instruction time (4 clock cycles) to execute, except if the condition turns out to be true, when it takes 2 clock cycles. This is to compensate for not executing the next line, and still be able to count total instruction time by simply counting lines of code, and multiplying by the instruction time factors, independent of the conditions being true or false.
The block of code from Delay2s_0 contains 7 instructions for each iteration. From the datasheet instruction listing we can see that goto's take two instruction cycles to complete, and it's beautifully written with goto $+2, jumping ahead 2 lines in the execution. So when the code starts out, d1 is 90, decfsz brings it to 89, proceeding to next instruction goto $+2 gives 1+2 instruction times so far, then another goto, and a final goto gives a 1+2+2+2=7 instruction times, before decfsz brings d1 to 88. The process repeats itself until d1 ends up at 0. At this time, the following goto is skipped, and instead d2 is decremented from 205 to 204, and proceeding along, counting the instructions, we see that the total still stays at 7 when we arrive back to Delay2s_0. At this time, register d0 contains 0, and subtracting 1 from it rolls it under to 255, as if the contents were 256, and the carry bit flag is set. So d1 contained 90 only during the first countdown, but for subsequent countdowns it will count from 255 to 0. So while d1 is no 0, we keep repeating the prior steps, 1+2+2+2 instructions, d2 staying at 204, while d1 goes from 255, 254, 253, ... 5, 4, 3, 2, 1 to 0, and at this point the skip if 0 becomes true again, and now the decfsz d2 instruction is executed, bringing d2 to 203. This process repeats itself, 204 times, with a total number of instructions passed 204*256*7+90*7, when d2 becomes 0. Now the decfsz d3 is executed, and similarly, by the time d3 becomes 0 we executed 21*256*256*7+204*256*7+90*7=9999990-1 instructions. The -1 comes from the final decfsz d3 skipping a goto - previously this instruction took 1 cycle to decf, and 2 cycles to goto, with a total of 3 cycles, but now, decfsz, with a true condition becomes a 2 cycle instruction, and there is no goto, so we lost a cycle 3 vs. 2. To compensate for that, there is a single nop executed next. There is an equation one can come up with calculate those values, but one may forget how it exactly goes when a quick delay routine is needed. Therefore the easiest procedure is to multiply 256 as many times as you need it, counting how many register varibales you will need, then starting backwards, 1 minus the trial number such as 21(trial number)*256*256*7(2*number of variables +1)... to get you under your target value, then repeat new trial number, 204(trial)*256*7(2*number of variables+1) to still keep you under it, and the final tweak, with the doublecheck like we just did. After a few times of practice all this will be a breeze, assuming you've had the patience to go through all this step by step. Patience is pretty much the most important thing for math. If you only saw what kind of lengthy things Leonhard Euler did when coming up with some of his formulas, such as, if I remember, Sum(1/x^2)=pi^2/6. http://www.physicsforums.com/showthread.php?t=80591 Lots and lots of patience and superaccurate methodical hand calculations. Most people throw in the towel long before him. That's what made him different from the rest of the world. Edison said genius is 10% inspiration and 90% perspiration. Tesla used to ridicule him on that, how he would go ahead and diligently start inspecting each straw right away when looking for a needle in a haystack, instead of first trying to figure out lazy ways to eliminate half the haystack by some logical reasoning first, if possible. But nevertheless the statement stands.

There are many ways to do delays, as listed at http://www.piclist.com/tecHREF/microchip/delay/general.htm ,some of them relying on deep subsequent "call" within another "call" which uses up a stack space. Stack space is at premium, especially on PIC10 and PIC12 series.

PS: it seems something is not right with the __config 0x3D09, and when I just uncomment that line, the LED flashes right.

Wednesday, October 14, 2009

Quote

"In theory, there is no difference between theory and practice. In practice, there is." - Yogi Berra

Thursday, September 24, 2009

From the Fall '09 Microchip 8 bit PIC brochure it looks like the PIC16F88 is kind of obsolete by now. The replacement seems to be PIC16F1827, which blows the pants off the F88 in price, speed, and features. However nobody seems to sell the F1827, while the F88 is still being sold everywhere.

Monday, September 21, 2009

Playing with an off the shelf el-cheapo soil moisture meter

Original article 9.21.2009.
PS. 4.2.2010 nice read - http://tuxgraphics.org/electronics/200908/eth-flower-watering.shtml

I just found a Bond 9628 Moisture Meter hanging at the junk section at Marcs, for $2.49. I just had to get it, out of curiosity. I know what such meters measure is nonsense, because the principle they are based on is nonsense. It looks like an analog millivolt meter, with a needle attached to an ultra-fine-wire wound coil. The minute amount of electric current passing through the coil wire creates a magnetic field that makes the coil deflect from another magnet or just a piece of iron, or even a second coil wound same or opposite direction - I don't know what exactly, I haven't taken it apart. The current is generated at the tip of the meter, by a battery action, by two dissimilar metals being immersed into an electrolyte. In this case the two metals seem to be a zinc and stainless steel. The tip is zinc, separated by what looks like a polyethylene ring, and the whole stem is stainless. The ionic conductive electrolyte is supposed to be the wet earth with the salts and ions dissolved in the wetness.
The idea here is that if there is a continuous wet path for the current to flow through the wet earth from the zinc tip to the stainless stem, then the circuit is completed, and the battery setup at the tip generates a voltage that deflects the needle. Here is where the first problem is, because according to theory taught in Chem 101, the voltage is independent of pretty much everything including amount of wetness, or salinity, except the concentration (molarity) of the dissolved zinc or stainless(or lowest redox species, such as hydrogen) ions in solution (Nernst equation). So according to theory the meter is an on/off device - there is either a continuous path, and then the needle is fully deflected, or there is a break in the circuit, and the needle does nothing. That is theory, assuming theoretical voltages. However the practical meter has internal conductance, and cannot measure just pure absolute theoretical voltages, only combinations of current flow and voltages.
Suppose the full theoretical voltage generated is, say, 1.0 Volts (measured by a meter with a huge internal resistance of say 40 megaohms or 200 megaohms. Our coil wound meter probably has maybe a few kiloohms - I will have to measure the resistance between the tip and the stainless stem). Now if the earth is partially wet, and its bulk resistance is (roughly )2000 Ohm/millimeter (there would be a complicated conduction field even in a totally uniform and isomorphous earth decaying beyond significance but theoretically going all the way out to infinity), so let's say the earth is 2000 Ohms as far as the meter can see it, and the coils internal resistance is 2000 Ohms too, then half the voltage drop happens through the coil, half the drop happens through the earth. In this case the coil would feel 0.5 V instead of 1.0 V. So basically we're measuring the electrical resistivity of earth, with a matched resistivity of the coil somewhere in the ballpark of interest. This is all well, except salinity is a crucial thing here - distilled rainwater is almost an insulator, while saltwater, or water full of putrefied ammonium, nitrate, sodium, potassium ions is very conductive. So the resistivity depends on the type and makeup of earth we're trying to measure. Very wet but nonconductive earth such as quartz sand would be after a rain, will measure very dry, but a quite dry as far as moisture content goes, but loaded with salts/fertilizer earth will measure as very wet, simply because it's more electrically conductive. Though there is a general correlation that the more wet the earth the better the conductivity - in regular earth such numbers are so far off the chart in either direction, that a meter measuring simply earth resistivity cannot tell whether it's due to moisture or salt content.
Moreover there is a porosity problem - compact earth with good contact area will be less resisitive compared to loose and freshly tilled aerated earth that may only have a few inadequately conducting point-contacts on both the surface of the meter, and through the bulk of the earth.
Basically, to measure moisture content of earth, the medium has to be very fixed as far as salinity and bulk porosity is concerned. All the meaningful methods to measure moisture content through electrical means first use a standard medium such as a rod of gypsum(plaster of paris) or a piece of polyimide to suck up moisture from the ground in an equilibrium quantity, and then measure the electrical properties of that standard medium (resistance or capacitance, aka. collectively impedance). Gypsum is sensitive to salinity, it soaks up the salts somewhat, but polyimide should only absorb moisture. Both gypsum and
polyimide of course would not have the variable porosity issue from soil sample to soil sample, but it takes significant time to equilibrate moisture levels inside the "moisture probe" (whether gypsum or polyimide.) Smaller physical size probes equilibrate faster, but also need more precise measurements, and even so the measurements might be spurious. The meter I bought is very fast, except what it measures so fast is meaningless. Standardizing the moisture measurement medium, and bringing it into moisture equilibrium with the surrounding earth is time consuming, but the results are at least more meaningful.
When I tried out the meter, fresh out of the wrapping, I stuck it into some tap water - nothing, no reaction, in standing water. I looked at the tip and it looked a bit corroded/oxidized. I tried dipping it into acid, the standard medium for batteries. The only acid I had handy was straight vinegar (acetic acid). When I dipped it, the needled went flying to the 10 mark, the very wet on the scale. So the thing works at least if it sees a proper and strong ionic electrolyte that it can react with. I noticed the zinc tip fizzing, and getting very clean very fast. After this oxide layer removing cleaning step, immersing it into tap water started moving the needle, but barely to 1 or 2. I'm like aha, I still need to add salts. I have no table salt, or i can't find it, but i found some baking soda, and I tried adding that. It gave a reading of around 5-6 in standing tap water with a pinch of baking soda. Then I added some of the vinegar, to generate sodium acetate, which is a good conducting salt, and the needle went to 10 in standing water. So the electrolyte quality does matter, a straight standing pool or tap water is not very "wet" as far as the meter is concerned, only if it has lots of dissolved salts, does it become wet. In most good topsoil conditions, that are properly fertilized, there should be a lot of dissolved salts, but in fresh leaf compost/mulch/rainwater type beds this may not be the case, and the meter might read dry even in a standing pool or rainwater on top of such bedding material, because of lack of salinity.
The interesting thing to see in the future is if sticking this probe into a gypsum stick would give more meaningful numbers, even if very slowly (may need up to an hour to equilibrate moisture content between gypsum and soil). Then all these el-cheapo moisture meters might even be used for something useful.

PS. Oh by the way it's funny how one can forget almost everything about microcontrollers in a few years, especially if the inital stuff never really sank in very hard (not enough practice, I only built like 2 custom circuits, the rest were programmers/kits, where you program in one slot, and do something else in the other.) So I pretty much started with the basics again, but it's a lot easier to relearn now than it was to comprehend it initially. It's still a hobby, and a fun past time.

Sunday, September 13, 2009

Low power low speed embedded wireless

http://www.embeddedstar.com/weblog/2009/06/09/sm-band-wireless/
Microchip released sub GHz wireless chips for their PICs, on the medical/industrial 434/868/915 MHz unlicensed bands. The base cost is $1.63 in units of 10K, and 2.35 for single units from Microchip direct. However the only package option is surface mount TSSOP, and a breakout board that makes soldering easier costs $39.99, available 9/28/09.

Moisture sensing

Lowest cost/fast response moisture sensing seems to be capacitive. The Honeywell HCH-1000-001 moisture sensing capacitor based on polyimide is $2.47 in quantities of 500. Getting a quantity of 1 from Newark or Digikey is on the order $6, and with shipping that's $10-30. This sensor isn't that special or high tech, it's basically a plate capacitor with moisture absorbing polyimide dielectric that changes values from roughly 300 pF at 0% RH to 355 pF at 50% RH to 380 pF at 100% RH. One might as well build one from just a thin film polyimide plastic itself, by electroless coating of metal on a small area (the total area decides the sensitivity/response time - small device time having fast response of water absorption, but lower overall change in capacitance magnitude.)
One would need a very sensitive PIC based capacitance meter targeted for this zone. This is a better way to measure capacitance, compared to off the shelf digital output ones, because one can throw two or more different frequencies generated by the PIC, say 100 Hz, 10 kHz, (100 kHz and 1 MHz needing bnc coax), and measure the RC time constant. Water absorbption into the polymer may have a characteristic ratio at different frequencies, compared to stray capacitance from nearby soil, or even electrical conductivity from absorbed salts such as nitrates. Different polymers might actually work better, such as PVAc, or PC. I see some polyimide tape at http://www.grainger.com/Grainger/items/3ZRA4?cm_mmc=Google%20Base-_-Adhesives,%20Sealants%20and%20Tape-_-Tapes-_-3ZRA4,
which could be tested initially on a large size with may layers stacked, and taped to alufoil, as a cheap capacitive moisture sensor. You have to calibrate out the stray capacitances anyway, and moisture sensitivity is what ultimately matters. Polyimide is very stable over time, but the degree that the adhesive glue contributes to the overall moisture sensitivity, and its variation over time might be an issue. One might need three different sensors for 3 different ranges, unless it's determined that soil moisture should be controlled between say 30-50 wt%, and then the relative humidity in air around it be say 60 to 90%, and then one sensor fine tuned for that exact region. Calibration of different RC time constants vs. humidity would have to be done with predetermined oven dried gypsum/water wt% mix ratios as humidity standards, and the constants stored in the PIC's eeprom. CaSO4.xH2O is a fairly pure chemical standard, as opposed to different soils, which vary widely.
I've had the opportunity in the past to work with Agilent HP4285A/HP16453B fixture dielectric constant measurement instruments for PVC that top out at 30MHz. There are some variations vs. frequency that might be water sensitive, and yield better calibrations compared to single frequency designs. Ideally water itself has a maximum dielectric constant change / tan delta near 800 MHz - 3 GHz, but that is out of the direct range of PIC's, plus special low signal loss waveguides would be needed at that frequency, unless the sensor and measurement conversion board are next to each other. Eventually we'll see.
I was originally going to use LCD's for a sensor, but simply adding a serial adapter, with an earphone plug to female DB9 convertor, to each microcontroller, and hooking up a laptop hyperterminal to it to see what it says, and what it's supposed to transmit wirelessly, is so much simpler and cheaper. You'd have to walk around with a laptop or serial pocket pc to debug why something is not talking on the wireless and to isolate fault. I still simmering in thoughts about the wireless part, and that is almost the most crucial thing expense wise here.

PS 9/15/09 - there is nothing high tech about the plate capacitor, except the way one of the metal surfaces is either porous/foamy, or has many tiny holes embedded in it, for fast moisture sorbtion throughout the dielectric. I guess one can duplicate it with alufoil and a needle pin, though not very reproducibly, and each individual item would have a very unique, but hopefully timestable and calibratable behavior.

Saturday, September 12, 2009

Microcontrollers

Trying to learn microcontrollers. Last time I had a go at it was 2004, with microchip PICs. Time to take it up again, as opportunity arises. It's just simply something to do if you can, the benefits you will understand later.

There are some new developments since 2004 in the world of microcontrollers, mostly toward the more complex, such as Arduino, but otherwise, the simple and low power things have stayed mostly the same since, with PIC16F88 still being a top contender, with prices around $5. If anything, the rise of 10F200 like 6-pin PIC's priced at $0.44 each is new. Most of the (old) tutorials relate to PIC16F84/84A, and to PIC16F628. A lot of the world has moved on to AVR, partly because of partly because of C being more available, and possibly design reasons I will learn/understand later, but to start out, and to understand assembly programming, PIC's are still excellent. Knowing this stuff would eventually pay off, besides the hobby reasons - automating simple or mindnumbing tasks and collecting better information about one's environment is something to get better at. Home automation, even factory automation is on the table, if you can only get good at it. Most factory automation is still stuck on PLC's and hasn't move on to microcontrollers. PLC's are tried and true and tested and therefore well trusted, but they suffer on cost and power consumption.

I have some samples Microchip was kind to send for free way back in 2004 - PIC16F84/84A, PIC16F628, PIC16F88, PIC16F877, and some of the 18F series. Also from Dallas/Maxim some DS18B20, DS1631 and MAX232. My life went in strange directions and I haven't really had the stability to sit down and toy with these things.

Moreover there was not a really good goal to gravitate towards. Now I have certain things in mind, such as greenhouse/farmer irrigation/soil moisture/quality sensor networks. For this cost has to be rock bottom, and $5 for a microcontroller is too steep, literally, so eventually, the 16F88 is off the chart after the learning period, and 18F series are out of the question. The 10F 6 pin series are a prime target, but the resources are so limited on it, that the 12F 8 pin series, or the lowest cost 18 pin 16F628-like ones may have to be settled for.

Ideally I'd like to find a an accurate and economical way to measure moisture content, and base irrigation on that. I feel there is room for improvement that hasn't been exploited enough. Electronic sensor technology is very advanced, and lots of freshwater resources are wasted on improper irrigation. However measuring, or even definition of ground moisture is a fairly touchy subject. Most top of the line measuring instruments measure water tension, and cost $100+, and require a meter that an operator would walk around with. Wireless setups cost in the thousands and farmers are likely to skip on getting such systems, simply on initial cost reasons, even if the water savings/proper not under or over irigation savings are worth it overall.

Sensirion has some digital SHT11/71 humidity meters, that after a trial/experimenting, might be in the proper range and scale to measure soil moisture directly. However their $30 price is way off the chart. There are some chinese knockoffs for $9.99, but that is still too steep. In the end one might have to go with a Honeywell analog moisture sensor for around $1-$3, and use the microcontroller A/D convertor, with manual calibrations. That is if capacitive sensing works well, and is not in the wrong range. There is a possibility that soil shows a 100% relative humidity reading for moisture content from 30-90%, and then it suddenly drops to near 0%relative humidity in the air at some number such as 25% soil moisture content. In this case the resistive sensing through gypsum/plaster blocks might be the answer. However gypsum dissolves slowly over a year into the soil and has to constantly be replaced. Also it may be dependent on contact area/soil texture for appropriate response time. Measuring ambient conditions of the air in soil as in capacitive relative humidity sensors would do, would make the measurement independent of texture/compactness. Ideally one would like to grab an off the shelf cheap item that does not need much custom fiddling around such as manual recalibrations, and it should last 10 years, if possible, without having to replace it yearly, by design.

For a reasonable setup many sensors would be needed on the very cheap, discardable if a tractor/cow smashes them, and ideally connected wirelessly, to keep cost and management spaghetti messes down. Most recent wireless standards such as ZigBee are out of the question, on reasons of cost/power consumption. RS232 on each sensor/microcontroller for local debugging via hyperterminal is a must, on reasons of simplicity. There is nothing simpler than RS232. Only the parallel port used to be simpler as far as hobby programming goes, but unfortunately it is no longer available on computers, that come only with USB anymore, and everything else available as an adaptor. Unfortunately the LPT port is gone, even with USB/parallel adapters, because those only work with high latency, for printers only. Bitbanging the USB stack would be a nightmare from the programmer's perspective, especially if one only has a limited resource PIC10F200. Ideally new computers would still come with a 9 pin RS232 port that could be converted in the BIOS to a low latency 9-pin parallel port, 8 bits+1 GND. The 25 pin parallel port is truly a waste on manufacturing labor, but 9 pins is a tolerable balance point. The USB protocol has too much packet processing latency for microsecond reaction time parallel ports. At least we still have good old RS232 that works well through USB dongles, but accurate timing requirements still make it harder to use than parallel designs, where the clock can be slowed down/sped up at will. But alas, accurate timing is no longer available on nonrelatime operating systems, and even realtime ones only guarantee reaction times on the order of 1 ms, not microseconds. In some cases, such as printing to an LCD through a parallel port, such timing issues may not matter, and a thousand instructions might be sent with 10 us latency, then there could be a 250 ms gap as the OS requires the CPU for other tasks, then it's returned and the program continues with its 10 us routine. Debugging parallel port things with a multimeter, by setting the frequency very low, to 0.1Hz or so in the program is very simple. So bit banged RS232 it is, unless the ucontroller comes with built in RS232. Bitbanging is still much fun.
The question is a cheap RS232/wireless/RS232 bridge, on the order of a few dollars. The nature of wireless is in question. The cheapest RF link ones with adequate range are custom FM setups on 3-400 MHz, but only one or a few can be used, for reasons of interference. According to http://www.sparkfun.com/commerce/tutorial_info.php?tutorials_id=128 Nordic has some very low power and adequate range chips, but all the other protocols, including wifi, bluetooth, etc. are very heavy and have extreme power consumption because of that. But even that chip functions in the 2.4 GHz band, making the range very short for a given power consumption, on the order of 10-50m. The lower the frequency, the deeper the penetration into such things as a forest full of moist leaves, and as long as the data throughput can be low, even long wave radio on kHz is more suited than 300 MHz setups.

I found interesting designs using laser pointers, that could be done very simply and on the cheap on dollar store items. http://www.geocities.com/siliconvalley/lakes/7156/laser.htm?200912 (yahoo killed geocities, but lot of webpages point to that old address, here is an exact copy http://www.qsl.net/n9zia/wireless/laser/laser.htm )
however the danger of staring into one, and having to maintain proper alignment may be too much an issue. There are high power infrared lasers in most CD/DVD burners, but some youtube videos show such high power cd burner LED's setting things on fire. Lower power infrared lasers might be safer on eye health, other than the heating effect that the eye is very sensitive to. Unfortunately the longer the range one wants to achieve, the higher the heating effect. Infrared beams are safer than visible because they don't directly excite human vision cells, but also not safer from heating effects, because they are invisible. (PS. 4.10.2010 -actually, the above thinking is incorrect, the blink reflex on visible lasers makes them safer than infrared, see wikipedia pages.) Infrared beams are visible with cheap usb webcams. One could use smaller power regular visible laser LED as a coherent partner beam for warning purposes. Such line of sight systems, if properly aligned, are safe from interference, because the light beams are localized, compared to most other wireless designs, where the signal spreads out in space on transmission, and not very directionally received.
Cheap long distance communication has always been done with light, with smoke signals or ship light morse code signaling. Without mobility requirements, with sensors that are meant to be stationary on the order of a year there should be a way to get line of sight, even if repeaters are needed around corners. The ultimate throughput and power consumption efficiencies lie with focused infrared/light beams. For high throughput through a thick forest one could erect tall repeater poles that extend above the canopy, and do line of sight light communication. Weather is an issue, but nothing beats not having to run a conduit cost-wise. Because of stand alone unhooked to the power grid nature, the poles would have to run off of solar cells/rechargeable batteries, and power efficiency would be crucial. But such setups should be able to cheaply bring even internet to even places like the jungles of Africa or mountaintops of Tibet.

The current off the shelf standard wireless setup with multipoint sensors is 802.11b/g/n wifi. For very few (6 or so) points Bluetooth can work over short distances through piconets, and I even have a Bluetooth to RS232 adapter, for $50, from a previous situation where the goal was to monitor a single sensor, a PH meter, and maybe control a valve based on the readings. This RS232 to Bluetooth wireless cost is obviously out of the question for farms, and most wifi to RS232 adapters run around $200+. TCP/IP is simply too complex and expensive to put on anything, compared to a simple serial protocol like RS232/485/1-wire/i2c. In the end one might go with the 433 Mhz links, and use it like a walkie talkie, with the microcontrollers turning them on and off, and broadcasting messages, and listening for ack to check for collisions and retransmissions. It can slow things down a lot, but monitoring soil moisture/temperature/pH needs to be done very infrequently.

pH would probably use colotrimetric dye/nafion membrane/led/optical receiver, that should be done for less than $5, but with a very limited pH range of 3 units (i.e. 4.5-7.5), or custom ranges based on indicator selection. The dye lifetime due to dye degradation might be an issue, but this should be still less expensive than standard glass bulb. Colorimetry could in theory do other things such as nitrate/ammonia/phosphate/potassium/calcium, though these are very difficult. Drying out of the membrane can render colorimetric packets useless, though a constant trickle of water from a bottle on a stick controlled by a microcontroller interfaced to a humidity meter near the other sensors can deal with this. Such sensor sticks stuck into the ground at 10 meters (greenhouse)- 50 meters (open field) intervals measuring soil moisture/temperature, wirelessly connected to irrigation solenoids and automatically calling for water as needed, plus showing a record of measurements on a computer log, could provide a farmer with better information and water/crop resource management. Such sticks could also be beacons for automated farm robots instead of GPS signals, to weed/harvest crops. Solar power or in dark areas such as mushroom growing, sacrificial iron corrosion battery based ultra low power microcontrollers might be doable. Iron is a plant fertilizer. Aluminum and magnesium might be more expensive and harder to corrode accurately.

In a greenhouse atmospheric CO2 levels may be a limiting nutrient under intense light. Replenishing it in a controlled way might increase crop yields tremendously. Unfortunately internal combustion engines nor heaters capture liquid CO2, because of the energy loss that would entail. One would probably need a fuel cell where oxygen is ionized and travels to the other side in a pure form, separated from nitrogen, and generates pure CO2+water, and the two could be liquefied and shipped as carbon fertilizer for a greenhouse. There is talk about carbon sequestration from power plants, and sticking it underground, but if storage of it could be done efficiently, and shipped around in bottles like propane is, or even as dryice in super insulated containers, making food out of it, and increased healthy human biomass, that would be a better idea.

So much of the world's happiness is dependent on proper nutrition, and historically, booming societies always formed near areas where plenty irrigation was available, with large food production surplus per capita, allowing the farmers support of specialization in society: priests, potters, blacksmiths, musicians. Usually such societies collapsed internally by overgrowing their new extended limits, so even plenty of food, not enough food is still eventually a problem, and staying within controllable limits populationwise is the only sustainable solution. World population boomed during the last century, mostly due to Haber-Bosch ammonia fertilizer derived from fossil fuels. As fossil fuels run out, agriculture has to be improved to maintain current population levels. Biotech is improving crop yields through genetic engineering, just in time, but something as simple as proper irrigation management can provide a great kick at the bottom line.

The current soil humidity / agricultural wireless sensor market is a mess, on the very expensive side as far as farmers are concerned. Farmers work extremely long hours, for very little pay, and support families on as little as $8000/year, which is very low, even if housing costs or other living expenses are less than for city dwellers. Farmers will spend $50K on a tractor, or more land, as soon as they can afford it, because that is directly and visibly related to productivity. Equipment directly eases their physical labor, and the muscular pain they can feel when they sit down. When to irrigate/fertilize, and how much, is a much more subtle topic, and usually winged, based on feel, or simple trial and error experiment over the years, because even the mistakes of a few kilos of excess fertilizer or hectos of water is an order of magnitude cheaper than a lab test, and even then, lab numbers don't directly correlate to crop yields, the experience of fertilizer/water vs. lab numbers, then lab numbers vs. crop yield has to be deducted from them. Economical and accurate measurement is difficult, but that's the only true way to do it efficiently, via measurement and numbers. Here's a quote from William Thompson (Lord Kelvin):

"In physical science, the first essential step in the direction of learning any subject is to find principles of numerical reckoning and practicable methods for measuring some quality connected with it. I often say that when you can measure what you are speaking about, and express it in numbers, you know something about it; but when you cannot measure it, when you cannot express it in numbers, your knowledge is of a meagre and unsatisfactory kind; it may be the beginning of knowledge, but you have scarcely in your thoughts advanced to the state of science, whatever the matter may be."

As long as we are on quotes from Kelvin, and on measurement, here's another one:

"You, in this country, are subjected to the British insularity in weights and measures; you use the foot, inch and yard. I am obliged to use that system, but must apologize to you for doing so, because it is so inconvenient, and I hope Americans will do everything in their power to introduce the French metrical system. ... I look upon our English system as a wickedly, brain destroying system of bondage under which we suffer. The reason why we continue to use it, is the imaginary difficulty of making a change, and nothing else; but I do not think in America that any such difficulty should stand in the way of adopting so splendidly useful a reform."