Friday 19 February 2016

OpenBSD, ATmega328 and Pololu USB AVR Programmer

This is what I have been poking around with lately: programming an atmega MCU without IDE, and minimum Arduino dependencies.  That's just the way I like it.  



Bought some parts from www.RobotShop.ca:

--Pololu USB AVR Programmer.
http://www.robotshop.com/ca/en/pololu-usb-avr-programmer.html
So far, happy with this little device.  I just wish I could figure out a way to program the MCU without a crystal. 

--ATmega328.
http://www.robotshop.com/ca/en/atmega328-arduino-uno-optiboot-bootloader.html.

I clearly prefer to do my stuff without IDE.  And doing this with OpenBSD is quite satisfactory.  There is actually a port of Arduino (http://openports.se/devel/arduino) which I also use and which is also without IDE, but I wanted to go a little further.  It's a nice learning experience.

So here is the Makefile, a file I borrowed here http://canthack.org/2010/12/programming-the-arduino-in-pure-c/#comment-57224/index.html (Programming Arduino in pure C).  Modified for my needs and adapted to recent version of OpenBSD. i.e. SUDO=doas...

AVRDUDE=avrdude -B3 #-V
OBJCOPY=avr-objcopy
CC=avr-gcc
RM=rm -f

MCU=atmega328p
F_CPU=16000000UL
BIN_FORMAT=ihex
PORT=/dev/cuaU0
BAUD=115200
PROTOCOL=avrispv2
CFLAGS=-Wall -Os -DF_CPU=$(F_CPU) -mmcu=$(MCU)
PROG=${.CURDIR:C/.*\///g}
SUDO=doas

.SUFFIXES: .elf .hex

.c.elf:
    $(CC) $(CFLAGS) -o $@ $<

.elf.hex:
    $(OBJCOPY) -O $(BIN_FORMAT) -R .eeprom $< $@

.PHONY: all
all: ${PROG}.hex

${PROG}.hex: ${PROG}.elf

${PROG}.elf: ${PROG}.c

.PHONY: clean
clean:
    $(RM) ${PROG}.elf ${PROG}.hex

.PHONY: upload
upload: ${PROG}.hex
    ${SUDO} $(AVRDUDE) -c $(PROTOCOL) -p $(MCU) -P $(PORT) \
        -b $(BAUD) -U flash:w:${PROG}.hex


A cool little C program to test things out:

#include <avr/io.h>              
#include <util/delay.h>          

const int sle=100;
int main(void) {
    DDRB |= 0b00111100;
    int i = 0;
    while(1){
        for(i = 5; i > 1; --i){
            PORTB = (1 << i);
            _delay_ms(sle);   
        }
        for(i = 2; i < 6; ++i){
            PORTB = (1 << i);
            _delay_ms(sle);   
        }
    }
}


The mandatory make && make upload output with limited verbosity...

 marst@milkway.my.domain:21:48:16
/home/marst/documents/programming/c/avr/blinkLED:
$>make && make upload
avr-gcc -Wall -Os -DF_CPU=16000000UL -mmcu=atmega328p -o blinkLED.elf
avr-objcopy -O ihex -R .eeprom blinkLED.elf blinkLED.hex
doas avrdude -B3  -c avrispv2  -p atmega328p -P /dev/cuaU0  -b 115200

avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.

avrdude: Device signature = 0x1e950f
avrdude: NOTE: FLASH memory has been specified, an erase cycle will be
         To disable this feature, specify the -D option.
avrdude: erasing chip
avrdude: reading input file "blinkLED.hex"
avrdude: input file blinkLED.hex auto detected as Intel Hex
avrdude: writing flash (310 bytes):

Writing | ################################################## | 100% 0.

avrdude: 310 bytes of flash written
avrdude: verifying flash memory against blinkLED.hex:
avrdude: load data flash data from input file blinkLED.hex:
avrdude: input file blinkLED.hex auto detected as Intel Hex
avrdude: input file blinkLED.hex contains 310 bytes
avrdude: reading on-chip flash data:

Reading | ################################################## | 100% 0.

avrdude: verifying ...
avrdude: 310 bytes of flash verified

avrdude: safemode: Fuses OK

avrdude done.  Thank you.


Monday 28 December 2015

Perl script for my I3 Status Bar

I decided to roll out mu own little script to handle my I3 window manager status bar.  It's a good way to get back into a bit of Perl.
I also wanted to roll out my own little JSON formatter.  I did not feel to need to go with what ever Perl module offers.  Still some fine tuning required.  It crashes when a song title contains a double quote.

#!/usr/bin/perl 
use strict;

sub toJSON{
    my $retval, my $left, my $right;
    my $sep;
    while ( $left = shift){
        if ($left eq "text"){
            $left = "full_text";
        } 
        $right = shift;
        $retval = $retval . $sep. qq/"$left":"$right"/;
        $sep=",";
    }
    return "{".$retval ."}"; 
}

sub getvol{
    my $vol = 0;
    $vol=`mixerctl outputs.master`; #outputs.master=150,150
    $vol =~ /=(\d+),/;
    return sprintf ("%.0f",$1/2.55);
}

sub getdate{
    my @months = qw( Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec );
    my @days = qw(Sun Mon Tue Wed Thu Fri Sat Sun);
    my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime();
    return sprintf("%s %s %s, %02d:%02d:%02d", @days[$wday], $mday, @months[$mon], $hour, $min, $sec);
}

sub getsong{
    my $retval = `/usr/local/bin/mpc current`;
    chomp($retval);
    return $retval;
}

sub display{
    my $song_, my $date_, my $vol_, my $weather_;
    $song_ = toJSON("text", getsong(), "color", "#808000");
    $vol_ =  toJSON("text", "Vol:".getvol()."%");
    $date_ = toJSON("text", getdate(), "color", "#9060f0");
    $weather_ = toJSON("text", checkweather(), "color", "#009000");
    printf ("[%s,%s,%s,%s],", $song_ , $vol_ , $weather_, $date_);
}

sub checkweather{
    my $epoch_ = time();
    my $filename = "/tmp/tmp.xml";
    my $fileage = time() - (stat($filename))[9];
    if ($fileage > 3600){ #Time to refresh weather data
        system("ftp -o /tmp/tmp.xml http://weather.gc.ca/rss/city/qc-126_e.xml");
    }
my $temperature="No data";
my $condition, my $pressure, my $humididy, my $windchill, my $dewpoint, my $windspeed;
    my $overnightcondition;
    my $titletagcount=0; #at 5th tag, get overnight conditions.
    # 0 : Gatineau
    # 1 : Warning
    # 2 : Current conditions
    # 3 : Night conditions
open(FILE,"/tmp/tmp.xml") || die "Failed: $!\n";
while ( <FILE> ) {
        if (/<title>(.*)<\/title>/ ){
            ++$titletagcount;
            #printf ("%d : %s\n", $titletagcount, $1);
            if ($titletagcount == 4 ){
                $overnightcondition=$1;
            }
        }
if (/<b>Condition:<\/b> (.*) <b/){
  $condition = $1;
        }elsif (/<b>Temperature:<\/b> (-?[\d.]+)/){
  $temperature = sprintf("%s°C", $1);
}elsif (/<b>Pressure.*<\/b> ([\d.]+)/){
$pressure = sprintf("%s kPa",$1);
}elsif (/<b>Humidity:<\/b> ([\d]+)/){
$humididy = sprintf("%s\%",$1);
}elsif (/<b>Wind:<\/b> (.*)<br/){
$windspeed = sprintf("%s",$1);
}elsif (/<b>Dewpoint:<\/b> (-?[\d.]+)/){
$dewpoint = $1;
}elsif (/<b>Wind Chill:<\/b> (.*)<br/){
$windchill = sprintf("[%s]", $1);
}
}
return sprintf("%s %s%s, Wind:%s, P:%s, RH:%s, %s", 
        $condition, $temperature, $windchill, $windspeed, $pressure, $humididy, $overnightcondition);

}

sub main{
    print '{"version":1}[';
    for(;;){
        display();
        sleep(5);
    }
}

main();

(.*)<\/title>/ ){
            ++$titletagcount;
            #printf ("%d : %s\n", $titletagcount, $1);
            if ($titletagcount == 4 ){
                $overnightcondition=$1;
            }
        }
  if (/<b>Condition:<\/b> (.*) <b/){
     $condition = $1;
        }elsif (/<b>Temperature:<\/b> (-?[\d.]+)/){
     $temperature = sprintf("%s°C", $1);
  }elsif (/<b>Pressure.*<\/b> ([\d.]+)/){
   $pressure = sprintf("%s kPa",$1);
  }elsif (/<b>Humidity:<\/b> ([\d]+)/){
   $humididy = sprintf("%s\%",$1);
  }elsif (/<b>Wind:<\/b> (.*)<br/){
   $windspeed = sprintf("%s",$1);
  }elsif (/<b>Dewpoint:<\/b> (-?[\d.]+)/){
   $dewpoint = $1;
  }elsif (/<b>Wind Chill:<\/b> (.*)<br/){
   $windchill = sprintf("[%s]", $1);
  }
 }
 return sprintf("%s %s%s, Wind:%s, P:%s, RH:%s, %s", 
        $condition, $temperature, $windchill, $windspeed, $pressure, $humididy, $overnightcondition);

}

sub main{
    print '{"version":1}[';
    for(;;){
        display();
        sleep(5);
    }
}

main();
</pre>

Sunday 23 August 2015

Setting up An Alternative Aquarium.

Inspired from the book of the same title
"An Alternative Aquarium: A Robust Habitat" that I just finished reading.

I will use my 20 gal long that I bought recently.  It was not really intended for this but for some dirt setup anyway.  I did not have a stand, so had to make one.  Good old 2X4 held together with home made ash dowels and 12 1/2in carriage bolts.  A coat of iron buff to throw in some color and a coat of Dasish oil still drying.  And I need to decide where to set it up. It might be my bedroom tank.


I dug out 2 full buckets of clay from the backyard.  Dug almost 2 feet down.  I don't fertilize the lawn.  So that should be ok.  There were some pretty big earthworms.  Then I need to decide if I go wild hunting for soil or if I use the pond soil I bought as this is what I was supposed to use before I read the book...

Haven't decided yet on the plants and fauna.  There will be a heater as it gets cold here in the winter.  No filter, just a pump.

Here is the pump setup.






Layering the substrate.  Clay from my backyard, pond soil and play sand.  Then time to fill up.  It's a myth that setting up a dirt tank is messy.






Adding some supports for land plants that get their water from the tank through a wick.  One of my dog, Pasha, helped with the watering mat I used to make the wicks.







The tanks as of 3 Oct 2015.  Fauna includes 9 White cloud mountain minnows and 1 hillstream loach.  As usual, pond and trumpet snails are part of the game.


Saturday 1 August 2015

Update on the River Above the tank.

Cala Lillies shooting high in both 75 and 15 gal.  29 gal not doing so well.






Friday 17 July 2015

Cala Lillies rooting in the river above the tank.

This is one week of growth for the cala lillies bulbs.  Growth is insane.  It is so far the fastest growing plant.


Tuesday 7 July 2015

Mario's over the tank river - part 2

There has been some modifications.  I did not like the outflows.  They take too much real estate over the tank.  I installed two bulkheads instead.  I lined the inside of the bulkheads with some textile to kill the sound and eliminate splashes.

I did a leak test overnight.  All seem ok.  I added some raiser blocks to give place for the filter intake.







Saturday 4 July 2015

Mario's over the tank river.

This little river will be installed atop my 75 gallon tank.  The river is the same length as the tank; 48 inches.  It is about 5 inches wide and just over 1.5 inches high.  It's not high, it will be low flow river with of course plants in it.  Bed will be lavarock with maybe some pieces  of drift wood.

This is the barebone box without the ends.  Because it's dadoes, just wanted to do a dry fit before glueing the parts together



This is the outflow.  Water will return to the tanks through this small opening.

This is some arrangements in progress.  I seived all the lava rock I have to get some smaller ones.  I am a little short in rocks.  I will throw some larger ones int.  I painted and varnished the outside of the wooden box.  The inside is line with a PVC pond liner.  Then I place a layer of geotextile then the rocks.