2011-02-05

SolarLight (9) - Powersaving Software

"It ain't over till it's over"... After a week of very cloudy days and mostly no charge, I found out that I needed to save more power and provide some late "adjustments".

The findings and solutions were:
- having a status output every watchdog reset was too much, too often (once every 8 seconds). A more reasonable status output is twice every minute. Displaying the status spent about 0.5% of the total battery capacity, but after an almost full discharge the lamp would only operate for another 2 or 3 days without recharging (i.e. a week of cloudy days was "deadly").
- even during the status display the CPU could be put to sleep during the status output (without using a timer but the watchdog).
- the detection of an external supply had to be changed from above 4.2V to above 4.0V, my external adapter would "kneel" to this voltage when the batteries were depleted.
- the output power levels function of the battery voltage also had to be adapted, even at the lowest level (around 200mA output) the battery voltage "kneels" quite deeply. So in order to take the most of the batteries I reduced the power output once the batteries are in the lowest charge (below 1.1V per element).
- another finding (with no solution as of yet) was that with AVRDUDE I cannot program the oscillator calibration value in FLASH (or EEPROM) automatically (as in AVR Studio). I'm not very "experienced" in script programming or makefiles with scripts but it must be possible. I need to program the flash with the code, then read the oscillator value and finally overwrite the flash (or write in a EEPROM) position where the code is getting this value. Since my program depends on this value for the switching power supply, I cannot be too away from the standard frequency of 1.6MHz.
Meanwhile I also updated my system to OpenSUSE 11.3 (yes, I know the new one is out... but I prefer "stability" over "bleeding edge").
The new code is pasted here
Ta Da for now!

2011-01-15

SolarLight (8) - Plastic Fixing Rig et altri.

In the new year I decided to further develop my SolarLight, I had to build a rigid rig to hold the light over my peppers vase. After some thought I decided to use plastic (polystyrol) to keep it lightweight. I used standard PVC glue (used for water/sewage pipes or spudguns) and Polystyrene.
To cut the boards I used standard hand tools (hand saw, metal file and sandpaper), thinking back I would be better off if I had used a table saw... With a good saw and speed setting I think I could do it all in one. I don't have a table saw, nor the space for it, maybe I'll use the Dremel mini-saw adaptor (Dremel 670) or one of the Proxxon mini/micro table saws.
The glueing of the parts was fast and clean, if you do something like this remember to do it out in the open or in a well ventilated place, toxic fumes come out while the parts are being chemically soldered. I found most of the plastic sheets and profiles here.


I started out by trying one of the few available 2D-CAD packages for linux, I used QCAD community edition that had a pre-compiled for my OpenSuse11.3 in the contrib repository. Learning a new tool has always it's steep learning curves, but I got what I wanted. I will try to use it for my future mechanical drawings of cases and front panels.



After the assembly I noticed that I forgot some openings for the LED connector and fixing, so it is just hanging for now. I also changed the battery pack I had for a 3x AA NiMH 2300mAh batteries. This was a mistake, the solar cell was selected based on a battery capacity of around 700mAh (an old NiCd pack I had laying around) and size of the board. Although with the batteries charged I got a good hour and a half of light, the next recharge period was a full week... from this page I would need 40 hours of sunlight to fully charge the battery as the solar panel output current is below the C/40 ratio... Taking into account that the average daily sunlight time of about 8h,(and in my south facing flat it's reduced to 4-5), that in Holland the sky is mostly cloudy for days in a row, that the solar cell outputs roughly 15mA with direct sunlight, I could expect to have a fully charged battery (with the NiMH pack) every two weeks.. With the NiCd I could expect once two sunny days (more or less what I was looking for). So I have to go back to smaller batteries, probably another junk 3x AAA NiCd pack I have around.
I also roughly measured the efficiency of power supply and made some tests. The maximum output current I managed was 700mA, more than that and the battery voltage would hit the under voltage protection I had built in, this is about 50% of the LEDs Power. I also had to add a heatsink to the LED as its temperature was rapidly increasing beyond the "can you touch it" capability (a rule of thumb I learned...). So I used a stable DC power supply and varied the input voltage, input current, output voltage and output current at about 25% LED power level (3.2V@300mA). The results are a bit disappointing, the efficiency is about 50% from the calculated 70%. I don't think the losses are semiconductor related but mostly the passive components (inductor resistance and capacitor inductance and resistance). The good point is that output voltage is mostly independent of input voltage...
I also did some improvements on the code and ordered some new SMD components, I'm planing on building a SMD version and extend the project to a bike light (with the electronics inside the lamp's casing), we'll see how that goes, later I'll publish the updated software.
I included a graceful degradation system to reduce the output power as the battery depletes its charge, the processor now sleeps between ADC conversions both to save power and reduce noise (I cannot disable the Timer as the PWM must run), I changed the charging process but not counting the hours of charge but only by checking the battery voltage as this allows an external charger (not sun) and finally I converted the code to be compile in linux (avr-gcc/gas).
It's a long post and I have some more post hanging in for further editing.. I'll try to keep up with one a week and I'm already falling behind.

2010-12-31

New Year's resolutions...

This year is coming to an end and this will be my last post (this year). I didn't post as many times as I wanted (I planned once a week, I'm close to once every two weeks), but that's the way life goes.
Most projects are "work in progress", so these are in plan for next year:
  1. in the mini68k I wanted to finish a working gdb-stub before advancing to the CP/M-68K code. I finally managed to make it work, but there were some bumps in the way. The way ahead is not without it's perils, to use gdb and CP/M at the same time I might need an extra serial port for which I have no breadboard space. I'll need to draw the schematics, possibly make a PCB, make the SDCard interface work and then port CP/M to it;
  2. in the mini85 I wandered off in some hardware questions (casing, with a floppy or without, processor speed, with DMA, cheap DMA, video, expansion, connectors, front panel, size of RAM, SD Card, SD Card removable, Flash or Eprom, serial ports, parallel port...). I'll need to settle down on the hardware, draw schematics, make PCB, fit in a case and close it;
  3. in the Solarlight project I still want to fit it neatly on top of my Pepper pot and to tune some more code, also add a larger heatsink for the LED. I also plan to do a new SMD PCB and bake the components in a SMD oven. Further, I'd like to build a bike light with the same circuit but no solar charger. I'll need to get the final schematic, draw the SMD PCB for solarlight and bikelight and make the code linux-buildable and downloadable;
  4. in the SBC6120 project I'll need to decide on how to fit everything inside the box and fix the harddisk to the PCB, also design the front panel, back panel and connectors.
  5. in the home monitoring project I'll need to rewrite the code for the new light sensor and adjust the pachube data to it.
I don't think I'll run out of electronics projects for next year, but if just in case I do, I have to change a pedal crank on my Kronan (got bent on a recent fall on the snow) and I'm waiting for some studded tires :-) , read some more books and try to reduce a bit the coffee intake...

2010-12-30

gdb-stub for m68k quirks and tricks

After some investigation I finally realized how most of the gdb-stub works and how you can make it work, I also found out what doesn't work and that there are some things I still don't fully understand.
After having a stub that I could download to the target's ROM (in this case an EPROM Emulator) and would properly communicate to the gdb running on the host, I built a C runtime assembly file (crt0.s) and linker command to place the program in the available RAM. Since I had done a similar work for the stub running in ROM, it was only a question of changing some parameters and some basic code at the start up routine.
The test program was very simple, I didn't want to test any advance feature just a simple program flow with loops.

When I added a coded breakpoint in the code, all would work consistently, I could continue without a worry, control flow would be transferred back to the stub when the breakpoint was hit.
But as soon as I added a gdb break point what I expected to happen was, gdb(host) would read the contents of the instruction at the breakpoint and substitute it by a breakpoint opcode (TRAP). From reading the gdb-stub code and most internet references, a breakpoint should be a TRAP #1 instruction, I had setup the gdb-stub to intercept TRAP #1 instructions and report them as breakpoint to gdb(host), but every time I place a breakpoint I would get a privilege violation at the address following the one of the breakpoint.
The problem was that gdb(host) instead of adding a TRAP #1 (0x4e41) would add a TRAP #F (0x4e4f) (!!!), see it in the below:
I set a break point at line 20 of the code, gdb(host) tries a Z0 command but the stub doesn't implement it, gdb(host) acknowledges it, then it reads the code at the breakpoint position (m4074,2 with reply 2039), then writes a trap instruction at this address (M4074,2:4e4f).

You'll need to click on it to see it ok, sorry couldn't solve this one in the old fashion way..
When after several tries I decided to check "everything" that came in and out of the stub, I check that the instruction is in fact a TRAP #F and not a TRAP #1 as I was made to think, naturally I had not set the gdb-stub to catch these exceptions, then the stub would return to the address following the trap which is not an instruction, hence the privilege violation.
This problem above is probably solve in some gdb configuration line, but I didn't found it yet.. If I do I'll post it back here.
The second problem is only detected when you get these breakpoints to work. After the breakpoint the PC is pointing to breakpoint+2, before you continue you need to roll the PC back by two. This can be done either by the stub or gdb itself. I chose to do it at the stub, but it is possible to do it at the gdb(host) (also some configuration option must be there...). The only problem with any of these is that once a breakpoint is hit, it must be disabled before execution continues.
Gdb(host) just before you continue changes the instruction at the breakpoint address to a trap, then execution continues, when the breakpoint is hit control is given back to the stub and the instruction at the breakpoint is replaced by the previous. If the PC is rolled back by two, at the next continue, the same breakpoint will be hit without further processing... so we are blocked... An option would be to control everything from gdb(host), before continue, single step one instruction (the breakpoint instruction), change the breakpoint by a trap and then continue... I will have to investigate a bit further to see if this is already implemented in gdb but it seems (as Mythbusters would say Plausible).
If you are also curious about why the coded breakpoint (TRAP #0) above is different than the gdb-inserted breakpoint (TRAP #1 or #F) it is because gdb-inserted breakpoints must roll back the PC, coded ones do not.