Dec 1, 2016

Wireless Temperature Sensor (nrf24L01 & DS18B20)

As I mentioned about IoT Gadgets in the last blog post, I've been developing an "home automation basestation" and gadgets which connects to that. The basestation (BS) itself is connected to wlan and my server via ESP8266. The BS has an DS18B20 temperature sensor and IR led, which controls my AC unit. It also has an nrf24l01 RF module for external wireless sensors and controllers. For now, I have only one wireless temperature sensor, which also has that same temperature sensor and RF module. More of that, the sensor module has ATtiny2313A microcontroller, 1.5 F 5.5 V super capacitor and a solar cell.

The sensor module would run almost forever with AA batteries but that would have been way too boring, so I used a super cap & solar cell combination to learn something new about the power management optimization, sleep modes and current measurement techniques. I also wanted to use an 8-bit AVR microcontroller at least for this revision, although for ex. Gecko EFM32 would have provided a lot smaller current consumption. Just for simplicity, I also left out the energy harvesting IC with solar cell MPPT tracking and buck-boost SMPS output.
Rev. 1 board. Click to enlarge
Just by looking at the operating voltage ranges of every component, the max. voltage of nrf24L01 is 3.3 V and min. voltage of DS18B20 is 3.0 V, so 3.0 V LDO regulator with a low quiescent current could power everything in this module. This sets the usable voltage range of the cap between 3 V and 5.5 V. The load acts as a constant current sink over the voltage range, if we average out the active and sleep state current consumptions. To calculate the time when the voltage of the super cap drops from 5.5 V to 3.0 V, we can use the formula: t = C * [(V1-V2)/I]. So for ex. 1.5 F and 20 uA would make 187 500 seconds, which is ~52 hours with the assumption that we don't put any charge in during that time.

The rev. 1 model was quite large because it had a jumper for every voltage rail, so I could measure the current consumption of any individual component. There was also 3 capacitors (1.5 F, 0.47 F and 330_uF) behind the jumpers so I was able to change the connected capacitance. Rev. 2 doesn't have these jumpers and has only one super capacitor, so it's a lot smaller.

Rev. 2 board. Click to enlarge
As I programmed the first working scratch (1 MHz clock) without any sleep modes, the current consumption was approximately 750 uA, which would drain the cap in 83 minutes. As the MCU stays in sleep state most of the time, we want to use the lowest power sleep state, which is "power-down". Power-down disables timers, except the watchdog, which can be used as a wake-up source even in that deepest sleep mode. Watchdog interrupt function is used to cancel the reset flag before the MCU resets. Just by adding the power-down sleep mode, the average current consumption goes down to 130 uA, which is still 5 times too much.
By lowering the MCU clock from 1 MHz to 250_kHz, enabling the "power reduction register" features in ATtiny, reducing the temperature resolution of DS18B20 from 12 bits (0.0625 °C) to 10 bits (0.25 °C), using the deepest sleep mode of the nrf24l01 and by pulling down any unnecessary microcontrollers pins, the current consumption goes down to 27 uA. Further, we don't really need a temperature reading every 8 seconds (longest WDT range), so the final revision of the program reads the temperature in one interrupt cycle, puts the MCU to sleep already during the 250 ms temperature conversion of the DS18B20 and sends the result it in another cycle. That gives one temperature reading per 16 seconds, which is still well enough, but drops the average current consumption to 13_uA.
Click to enlarge
Download files:

Proteus 7.7 schematic & layout files (zip)
Atmel Studio 6.1 project / source code (zip)

As there is no step-up converter / energy harvesting IC, the open circuit voltage of the solar cell should go quite easily to 5 volts even in mediocre lighting, so the voltage would be higher than capacitor's voltage to allow the charging. The series schottky diode prevents the current from going in wrong direction when there is not enough light for charging. When there is lots of light, the charging voltage needs to be limited to 5.5 V, so the super cap won't blow up. That's done by using a voltage supervisor IC, which controls the mosfet and shorts the solar cell to ground through the 220 Ω resistor, if the voltage goes too high. Zener diode would have been a "single component solution" but they tend to be too leaky in non-conductive region, so it wasn't an option.

Click to enlarge. Sensor module with 2300 uF capacitor(s) as a power supply. Low voltage detection off vs. on
The recommended minimum input voltage range of 3.0 V LDO regulator is ~3.1 volts, but at that low currents, that specific LDO seems to works well above this, although the output voltage obviously starts to follow the input voltage when it goes above 3.0 volts. ATtiny2313A doesn't have an ADC which could be used for voltage monitoring, and the Brown Out Detector would be a bit too extreme, since there's no other option than resetting the whole MCU when it triggers. But there is an analog comparator, which can be used by connecting the internal bandgap reference (1.1 V) and comparing it to the operating voltage, divided with two resistors. I used 100k and 75k resistors, which makes 1.29_V when the operating voltage is 3.0 V. When the operating voltage dips below 2.56 V, the output of the resistor divider goes below 1.1 V and triggers the analog comparator. However, bandgap reference consumes a lot of current (~15 uA) so it's turned on only during the voltage test for a short period of time. If the voltage reaches that point, the DS18B20 doesn't work properly anymore, and measuring the temperature & sending the results are stopped to save some current. At that point we can also send a low voltage warning to the BS. There's also a routine which resetes the system occasionally if the low voltage is detected, so the memory of the MCU, RF module or the digital temperature sensor is refreshed to prevent corruption of the memory and malfunctioning of the system.

Currently I'm logging the temperature readings to my RPi 3 server (just for fun), and the module seems to work very well even in indoor lighting, without a direct sunlight. Next I'm going to put this outdoors when I'll find a good case for it.

Raspberry Pi UPS from junk box

I've been using the Raspberry Pi 1 as an ssh shell for Irssi and as a web server for my IP cameras and self-made IoT gadgets. Maybe I had just a bad luck with the corrupting SD cards, but I ended up to put the Arch Linux and other files to 120 GB SSD (although the SD card is still needed for bootloader), which was connected to RPi via 2.5" USB HDD box. Some time ago the SSD died and I got a good reason to upgrade the whole system, so I bought the RPi 3 and replaced the SSD with an 250 GB Samsung 840 basic. The extra performance (1x 700 MHz vs. 4x 1.2 GHz ARM cores) is nice especially when rendering timelapse videos from my IP camera photos.

Click to enlarge
To get some extra reliability, I thought that some kind of UPS could be nice. There's plenty of complete kits on ebay, but I happened to have some suitable parts in my junk box, so I didn't bother to wait 2 weeks. It wouldn't need any fancy features, but obviously should have at least an overcharging protection and under-voltage cutoff if the power outage is long enough. So there's the plan:

Click to enlarge
To keep it simple, there's no separate charging circuit for the 12 V sealed lead acid battery. I had couple of 12 V power supplies so it could charge the battery up to 12 volts. However fully charged battery would sit around 14.2 volts, so charging it only to 12 volts would waste about half of it's full capacity (2.9 Ah). For me, that's not a problem because the RPi would stay on more than long enough even with 1.45 amp-hours. We can limit the charge current of the battery with the 47R resistor, but allow higher discharge currents through the schottky diode, when the primary power supply cuts off. Theres also a protection diode for the 12 V power brick, so it cannot draw current from the battery when the main PSU is down. At these voltages we don't have to care about overcharging the battery.

RPi requires 5 volts, so there's also a regulator. Because the voltage drop from 12 V to 5 V is quite large when considering the 400-1000 mA operating current, I chose a buck switch mode power supply module instead of regular LM7805 linear regulator. That Murata module is pin-compatible with LM7805 but the efficiency is a lot better as it's an SMPS.

The undervoltage cutoff prevents the output of 5 V SMPS module to fall down slowly by causing all kind of unwanted effects for the RPi. When the battery voltage reaches ~6 V, the relay disconnects the battery, which is connected again when the main 12 V supply returns. The coil of the relay is rated for 5 volts, so there must be a series resistor to limit the current. The value of the resistor sets the cutoff voltage. But why there's a capacitor in series with relays coil? I noticed that when the resistor value would be good in terms of cutoff voltage, the relay didn't switch on even at 12 volts. So the capacitor works as a high-pass filter which bypasses the 270R resistor and provides the "kick" to the relay coil when the main PSU turns on, but after that, the current passes only via the resistor, as the capacitor cannot pass DC current. After the transition, everything abouve 6 volts is enough to keep the relay switched on.

Click to enlarge

* The picture above still with the RPi 1 model B.

Aug 18, 2016

30 MHz DIY Signal Generator (part 1)

A year ago I started this simple, microcontroller based DIY signal generator project which was capable for approximately 60_kHz sampling rate. However, that ended up to be quite boring becase I need test signals with higher bandwidth in my projects and there's already couple of similar MCU based signal generator projects on the internet. One idea leaded to another, and now I have dual channel, 90_MS/s, 30_MHz, 16-bit self-made arbitrary waveform generator (AWG). This won't be a complete step-by-step tutorial to build a similar one, but I'll try to explain enough details to give a good overview about the system. Also, the HW design and source code will be released, if someone wants to build one or even develop it further!

Click to enlarge
The user interface (UI) is managed mostly by the Atmel ATmega microcontroller. The signal generation itself is done in FPGA, which controls also the LCD screen, and couple of other miscellaneous tasks. The digital signal goes from the FPGA to the high-performance DAC through the 2x 16-bit parallel bus, and the analog signal passes through the low-pass filter, to the high speed op-amp and output BNC connectors. The low-pass filter is needed to remove the unwanted alias frequencies.

Analog bandwidth__30 MHz
Sample rate90 MS/s
Channels2 (+one internal modulation gen. / ch.)
Voltage swing±8 V (±4 V to 50 Ω load)
WaveformsSine, Square, Triangle, Saw, Noise, Arbitrary__
ModulationFM, AM, PM, Frequency sweep
Others2.8" TFT touch screen,
3 rotary encoders,
10 MHz clock reference input (BNC),
2.5 PPM internal clock reference,
USB remote control & SW update

Click to enlarge
The first prototype was built by using a Lattice XO2 breakout board (~$25) and self-made ATmega328P development board. The DA converter was implemented with two 8-bit R2R ladder DACs. There was no LCD or control knobs attached yet, but all the commands was given via virtual COM port (FTDI FT232RL) to the MCU, which controls the FPGA via SPI bus.

Click to enlarge
The next step added the LCD screen, control knobs and a frontend low-pass filter & amplifier (TI_THS3001) testing board to the prototype. The DAC component (AD9747) was not tested in this prototype, because the breakout board just for that would have been quite expensive due to the price of the DAC IC (~$30). Instead of physical breakout board, the DAC and the analog front-end was simulated by using Agilent Advanced Design System, and the simulations ended up to match pretty well to real-world performance tests.

Click to enlarge
Download schematic:
PDF File (rev 1.0)
Proteus 7.7 Schematic file (rev 1.0)

As you may notice, there is no separate JTAG header for the FPGA, but there's a ISP header for flashing the ATmega MCU. After flashing the Chip45boot2 bootloader to the MCU, the ISP header isn't needed anymore. The Lattice XO2 breakout board has a FTDI FT2232H USB interface IC which is programmed to USB-JTAG bridge configuration. The same IC is utilized also in this design, but more of that, it has also a USB-UART bridge functionality, so both, the MCU and the FPGA can be programmed via the single USB connector. The USB-UART bridge also allows the debugging and remote control features for the MCU.

The schematic design of the front panel leds & knobs may look a bit strange at the beginning, but the idea was to use as few MCU pins as possible for controls. All of the signal wires are connected to ADC pins of the MCU, which switches these pins very rapidly between the input mode (reading the values of knobs) or the output mode (feeding current to the leds). Depending on the voltage value, the MCU deduces the position of the switches. More common way would have been to place an extra MCU to front panel PCB for knobs & leds and the communication would pass through I2C bus, but again, this solution was chosen to keep the design as simple as possible (and to try something new). As an after thought, it works quite ok after tuning the ADC treshold values, but in my next AWG project I'd use a separate MCU for controls.

As the XO2 FPGA has a quite nice clock manipulation features built-in, I used a temperature compensated crystal to provide an accurate clock reference for the signal generator core. However, if even that isn't accurate enough or the clock of the different devices needs to be synchronized, there's also a input BNC connector for the external 10 MHz clock reference, and the internal clock MUX of the FPGA selects the clock, that is selected from the UI menu.

To keep the design as simple as possible, there is no variable gain amplifier or even separate DAC for offset leveling. This compromises in the resolution of the AWG, since the smallest possible voltage step is 16_V_/_2^16_=_0.24_mV in any voltage or offset scale.

Click to enlarge
The design was fitted into 50 x 100 mm 2-layer PCB, which was ordered from ITead Studio. There was only one bug, which was easily corrected with a piece of copper wire, so I decided not to order a new revision. Also the 5 V linear regulator, next to the power connector was replaced with SMPS module, which gives a lot better efficiency. The front-end op-amps still have linear regulator for the best possible noise performance. Power rails of the DAC are well filtered and regulated with LDO regulators, so the switching noise wouldn't pass to the signal outputs.

Click to enlarge
The project box (Bahar BDA-40004-W200) was ordered from AliExpress, and modified for all the knobs, connectors, leds and the display. The layout was designed in 3D modelling software to make sure that everything fits nicely and the placement looks logical. Someone may like separate buttons, but I'm a fanboy of rotary encoders, so there's three of them! One controls the selected menu item, another the digit of the selected value and third knob controls the value of the selected menu item/digit.

Click to enlarge
All the necessary pieces fitted into that project box. The main power supply is implemented by using IEC power connector with fuse holder & switch and 230 V to 2x15 V toroidal transformer. AC voltage goes to the PCB with fuses, MOVs (over-voltage protection), rectifier and bypass capacitors. +-21 VDC voltage passes to main PCB. The transformer with 2x 10-12 VAC outputs would be ideal, but I happened to have this 15 VAC model already, so it shall be good enough, althoug the output voltage is a bit high.

WARNING - Do not attempt construction of the power supply if you do not know how to wire mains equipment.

Well, that was quite broad description about the project. The Part 2 will include the PCB design files, source code, description about the program and performance measurements. Please, Tell me in the comments, what else you want to be included into Part 2!

Jun 20, 2016

Case mod: Fractal Design Define Nano S

Maybe not that much electronics related, but lately I've been doing this computer case mod project. Last years my computers have been in a ~105x40x25 cm closet with three Mobo & PSU mounts and four 120mm Noctua fans. Since my main computer is on 24/7 and I'm sleeping in the same room, the box is covered with sound absorbing material.

Click to enlarge
That's a good solution as long as I don't have to move the computer. But having a LAN Parties twice a year have been a bit problematic, since I have to disassemble the computer to the cardboard boxes and assemble it again at the party place. Also, the TV stand / Computer closet may not come along to my new apartment in the future, so its a good time to invest into a proper computer case. I already have some mATX cases and a huge full tower, but neither of them wouldn't fit into my needs. I've always liked the look of Fractal Design Define series cases, but they are just too big to fit nicely in my apartment, or to be carried around even twice a year. Lately Fractal Design released this very good looking Define Nano S case, which would be perfect unless it wouldn't support ITX motherboards (170x170 mm) only.

Click to enlarge
But wait, the Nano S case measures 203x330x400 mm so the ATX motherboard (305x244 mm) would fit into it after a bit of dremeling. Because the placement of the power supply was changed and the hole for motherboard's I/O connector had to be moved upwards a bit, the easiest way was to buy a 1.5 mm thick aluminium sheet and re-make whole back side of the case. The motherboard tray was taken off from a full ATX tower and cut down to fit into this chassis.

Click to enlarge
Maybe the worst thing in Fractal Design's Define cases are the overly bright blue PWR & HDD leds, which were replaced with dimmer green & orange leds. These won't illuminate the entire room at night. I have a 250 GB SSD for the operating system and 3 TB HDD for everything else. There's also a custom made HDD mount, which have a ~3 mm thick sheet of rubber between the HDD mount and the case. This absorbs very efficiently the constant humming noise of the 7200 RPM HDD. The plate on top of is sized so that the whole thing can be mounted easily to the 120 mm fan slot.

Click to enlarge
Although the new placement of the PSU won't allow big CPU coolers to be used, my Prolimatech Samuel 17 seems to manage with the Xeon E3-1230v3 CPU just fine (idle: 38°C, load: 65°C). There's a 120 mm CPU fan blowing towards the PSU, so the hot air goes out directly, through the PSU.

Until now, my backing up solution has been a bit fiddly, but now I decided to include a 3.5" hot-swap HDD mount in the back side of the case, so I can easily insert a HDD maybe twice a month, and put it somewhere else, so it's completely offline when not used.

There's also four timelapse videos about the modding process and the end result (end of the part 4):

Dec 13, 2015

Merry Christmas & Happy New Year 2016!

Click to enlarge

Year 2015 was quite busy so not many blog posts lately. However, I've been doing ATmega324P & Lattice XO2 FPGA based dual channel arbitrary function generator project with 90 MS/s sample rate and 30 MHz analog bandwidth. That should be out during 2016!  #NewYearsResolution
 
Click to enlarge

May 29, 2014

DIY USB soldering microscope

I've been looking for a decent and cheap USB microscope for SMT soldering. Many of these 50-100$ Chinese microscopes have quite poor working distance, resolution and image quality so I thought to try make one by myself.

A webcam should work quite nicely as a camera sensor because they should work almost everywhere without fiddling with drivers or viewing programs. Logitech C270 is quite inexpensive and it have 1280x920 resolution. A bit of googling also revealed that it doesn't have any too fancy autofocus features that could cause problems later. Estimating the delay between camera and monitor from internet reviews was quite hard but it seems to be in tolerable level.

The lens is maybe the most critical part of the system because it defines the working distance and the amount of light that gets to image sensor. I came across the 50mm F1.4 CCTV lens from dx.com which seemed to be quite good for this project. 50mm may not sound like much enough for proper zoom level but this 50mm is with 2/3" image sensor. If the sensor is smaller, also the effective focal length gets greater because of cropping factor. I estimated that it should correspond something like couple of hundreds millimeters focal length with C270's image sensor. Minimum focus distance of this lens is ~30cm. It's a bit too long but focusing range can be modified by moving the sensor closer or further away from lens. The lens have adjustment rings for aperture and focus so finding the best configuration shouldn't be too hard. The lens package contained a threaded macro adapter so now theres also complete lens mount for my camera casing.

Click to enlarge

After taking apart the webcam and checking that everything works as planned, I got small black plastic case from local electronics store, drilled coule of holes, glued macro adapter to it's place and installed 1/4" tripod threads to case.

3. 85x55x30mm WCAH2855 plastic case

Total: ~ 63€ / 86$

Image quality, depth of field and delay is certainly good enough for typical hobbyist-level SMT soldering but I found that I'm still using bare eye for soldering because it's just more handy unless parts are 0402's or smaller. For after inspection and troubleshooting this is very useful. And if not else, it's still quite nice toy!

Click to enlarge
I've tried couple of softwares that are capable of showing webcam view. VLC had horrible delay, VirtualDub works fine but it doesn't allow real time effects like flipping the image horizontally and vertically (handy if the object is between you and camera as in the picure above). Open Broadcaster Software have also webcam input and it allows real time image flipping so I ended up using it in preview mode.

Edit 1: VirtualDub manages also real time effects! See instructions in comments below.

Edit 2: As one of the readers pointed out in the comments section, I forgot to mention that removing or covering the green led on the PCB might improve the image quality (reduces the amount of unwanted scattered light inside the box).  


 *A few glitches in video are caused by recording software, not the camera itself.

Sep 7, 2013

Mascot 719

Got a "new" Mascot power supply to my workbench

Click to enlarge

I didn't expect very much from it but actually it's quite accurate and good power supply after one modification and calibration. At the beginning analogue voltage meter had about 0.5-0.7V offset. That may even break things especially in low voltages (for ex. 4.0V instead of 3.3V).

Datasheet says that it have <1.0mV load regulation @ 15V output, <1.0mV line regulation @ 2A load current and ripple voltage should be under 0.3Vrms. Sense wires are also quite nice addition.

After some tests I opened it up and  found a few calibration potentiometers. None of them appeared to affect volt meters offset until I found a place of potentiometer that had been replaced with ordinary 81k ohm resistor (series with meters coil in voltage mode). That was quite easy to replace with a 100k potentiometer and now it seems to be bang on!

Click to enlarge
Considered also beefier components to zener regulator that seems to get really hot.
..but then thought that if it have worked that many years without any problems, it won't break anymore :) 

Before and after the mod:
Images before and after the calibration:
Click to enlarge
 Current reading seems to be OK.
Click to enlarge

Edit: One of the readers asked about PCB pictures. Download here

Jun 15, 2013

AVR I/O labels

Just a quick update - that's one hell of a handy "mod" to AVR micros! Not a new idea but makes your life easier.

Click to enlarge

Images can be found from http://www.blue17.elektroda.eu/mikrokontrolery-avr/1411 or by googling "ATmegaXX sticker".

Mar 28, 2013

Experimenting with AVR micros and VGA signal

Ever since I saw this (Craft by lft) MCU demo that won the Breakpoint 2008 Real Wild demo compo, I've been wanting to be able to do something similar. Well..it's still quite a long way to that kind of masterpiece but in this first part I'll clarify a little bit about the principles of generating the VGA-signal and also some "as simple as possible" code examples.

Basically the VGA signal consists of red, green and blue analog signals and H-sync & V-sync digital signals (5V). As you may guess, the voltage (0.0 - 0.7V) of each R/G/B wire tells the intensity of its colour. H-sync pulse is carried out after the end of each horizontal line and V-sync after each drawn screen.



























This is an illustrative view of one frame. Of course the real one would have 480 horizontal lines as this have only 11 for clarity. The easiest way to understand the picture is to think about old CRT (cathode ray tube) monitor. When the ray "hits" reactive material of display's inner surface, the area glows for a while. When this happens often enough (60Hz) we'll see steady image.

The beam draws the image quite much same way as you could write a letter (maybe slightly faster :) ). It starts the screen from upper left corner, writes the first line by going right, then H-sync signal tells that it's time to start the new line so the beam moves to the beginning of the next line and then start writing again. After reaching the end of the first frame, V-sync signal tells that it's time to start the new frame and all this starts again from the upper left corner of the screen. As the monitor draws 60 frames per second, there's 60 V-sync pulses and 31440 (60 frames * 524 lines) H-sync pulses per second. Because it takes some time to relocate the beam at the end of line or screen, there's "blanking areas" (bluish areas in the pic) where the beam is still going but it's actually outside of the visible area of the monitor. In these areas (front and back porch) R/G/B outputs have to be at 0 volts. It's common technique from old game consoles to use these blanking areas to generate audio and run other calculations when all the cpu time isn't going to generating of video signal.

After that you may realize that generating vga signal isn't so complicated as itself but the timing is everything! While the ray travels about 10 kilometers/second (6.2 miles/sec) there's no space for timing errors as we can see later.

The following figure shows all 5 signals relative to each other. Note that V-sync graph isn't in same scale as others.


24-bit image, 16.8M colours
6-bit image, 64 colours
Exact timing values can be found in here. The ideal clock speed for microcontroller would be 25.175MHz because with that clock speed every needed delay/timing would match exactly with N*clock cycle. But no worries. Monitors can stand fairly well small differences in timing values and frequencies so also other clock speeds can be used by calculating the closest possible delay times you can archieve with your particular clock frequency. The most important thing is that H-sync pulse and active video signals doesn't have any timing differences at all. Jitter in these causes wobbly and shaky image.
As you may deduce, the vertical resoluiton is always that same 480px in this display mode but the amount of horizontal pixels doesn't matter at all. For example if every R/G/B line is kept in same state whole active video sequence (25.4us) you'll get one pixel that is very wide. Or if rgb output values are changed every 0.254us, you'll get 100px wide image. Because of limitations of ATmegas processing speed we can't reach the full 640x480 resolution. The next reasonable step down is to draw every pixel twice as wide and every line also twice. Now we have 320x240 resolution. ATmegas should be fine with that.

These common ATmegas are 8-bit MCUs so it means that you are able to set only 8 output pins at once / simultaneously. This limits the max reasonable bit depth to 8-bit (256 colours). Because 3x 2-bit DACs would make only 64 colours and 3x 3-bit wouldn't fit in 8-bit limit, we could build 3x 2-bit DACs and then use the extra 2 pins to control the brightness of the colour so we get 256 colours. I used only 6-bits in my first experiment so there's 64 colours.


Click to enlarge

Assembly would be ideal language to write the vga code because you don't have to guess what C compiler is doing behind the scenes and you'd be able to optomize your code to run as fast as possible in every situation. I decided to save the ASM codes for a possible part 2 and made everything with C. I started by trying different techniques and ended up to use timer interrupt service that draws one line and H-sync every time when called. It also controls vertical amount of the lines and V-sync pulses.

My first working vga-code printed some "binary stripes" to screen. It simply counted from 0 (0b00000000) to 63 (0b00111111) and put the results in PORTC (3x 2-bit DACs connected to pins 0-5). Here it is presented as pseudocode (not any real programmin language or even fully working program, just easy to understand the idea):

// Timer interrupt service presented as pseudocode

ISR(timer1 interrupt routine){  // Runs every 31.8us
    line = line + 1;
    wait;  // Wait for 0.84us "front porch" after previous line
    turn HSYNC on; // 0 volts
    wait;  // Wait 3.8us (keeping the HSYNC active)
    turn HSYNC off; // 5 volts
    wait;  // Wait for 1.9us "back porch" before starting active video sequence

    if (run if line is 480 or less){  // If line is in visible area, run the code that produces the image.
        for(run 64 times by counting from 0 to 63){  // Counts from 0 to 63 in PORTC
            PORTC = value of for-loop variable;  // Set output
        }
        PORTC = 0; // Print black screen after the stripes (right side of screen)
    }
    else if (run if line is 492){
        turn VSYNC on; // 0 volts
    }
    else if (run if line is 494){
        turn VSYNC off; // 5 volts
    }
    else if(run if line is 524){ // One frame is complete, start another in next round.
        line = 0;
    }
}

Source files for ATMega32 @ 16MHz:

binary_stripes.c
vga_moving_palette.c

Fuse bits for ATMega 32:
-> High: 0xD9
-> Low: 0xFF

Fuse bit calculator: http://www.engbedded.com/fusecalc/


The code above should print stripes like that (slightly different colours but same principle). I had only 16MHz crystal so the horizontal resolution was quite poor. That was maybe the simplest vga program you can make. The next step could be adding some objects and specific colours. Simple square-shaped colour pattern might be quite easy to implement after understanding inner working of that first program.

In the second code example (colour pattern table) I used 8x8 array where all the colour values are stored (0bxxRRGGBB). For example:
0b00110000 = pure red 
0b00110011 = violet 
0b00000001 = dark blue
0b00111100 = yellow
And so on..

The square is made just by limiting upper and lower borders by testing that "if line is less or more than..." and same thing for left and right borders but at this time we'll modify the same for loop that made "binary stripes" in the first example to get the values from the array instead of just counting from 0 to 63.

At this point we got the first timing issue. When we are testing during active video sequence if it's time to change the row of the array, every last line of the specific pattern keeps going longer than others because processing takes some clock cycles more than normally (click the image to enlarge -> ). Of course it's possible to balance the delays with different tricks but it will be endless amount of work with C if the program grows bigger.

Since the whole 320x240 sized "display memory" won't fit in ATmegas RAM, we should manage to get the algorithm that uses blanking areas to prepare the incoming line beforehand and store only that to RAM at once. 




 
Ok. That was it for now. Let's see if I'll find some time to make part 2 with real-time calculated graphics, better optimized ASM-code and audio.

Feb 3, 2013

Sauna simulator

I've been asked to upload the video about that device so here it is now :)




















As the video tells, it have ATMega 1284p SMD 44-pin microcontroller, 35 SMD leds for the flames and embers, SD card and speaker for sound effects and NTC thermistor that detects the heat from lighter.

All the leds are controlled by PWM signal. Because the MCU have only couple of PWM lines, I used one 10-bit hardware PWM line for red leds (embers) and any of the yellow leds are driven by 3-bit software generated PWM. Unfortunately I'm not able to publish the source code or schematics about that because it was one of my school projects (so the next year students won't copy it). 



Got the replacement for my old and energy-hungry home server (Apple Power Mac G4). Raspberry Pi consumes only ~5 watts while my current server draws something like 60-80 watts. Both of them runs Debian linux well enough and the performance levels are about equal. 
At least it isn't too big if compared to 30 years old processor DIP package.

Raspberry Pi  vs  TS68000