Gather HP iLO information using PowerShell

2014-03-11 1 comment

Please begin by reading my previous post where I show how to retrieve physical hard disk information such as model numbers and firmware versions using the HP Insight Management WBEM providers.

A few days ago, as HP published an advisory regarding firmware of their Integrated Lights-Out (iLO) management controllers I wanted a way to collect this information from a number of servers. I created another CmdLet to retrieve information from two associated classes.
Namespace: root\hpq
Classes: HP_MPFirmware and HP_ManagementProcessor

For full details about the properties in these classes as well as the rest of the HP WBEM classes, download the latest version of the PDF document HP Insight Management WBEM Providers for Microsoft Windows Data Sheet

The Get-HPiLOInformation function

function Get-HPiLOInformation
{
    <#
    .SYNOPSIS
    Retrieves iLO management controller firmware information
    for HP servers.
     
    .DESCRIPTION
    The Get-HPiLOInformation function works through WMI and requires
    that the HP Insight Management WBEM Providers are installed on
    the server that is being quiered.
     
    .PARAMETER Computername
    The HP server for which the iLO firmware info should be listed.
    This parameter is optional and if the parameter isn't specified
    the command defaults to local machine.
    First positional parameter.
 
    .EXAMPLE
    Get-HPiLOInformation
    Lists iLO firmware information for the local machine
 
    .EXAMPLE
    Get-HPiLOInformation SRV-HP-A
    Lists iLO firmware information for server SRV-HP-A
 
    .EXAMPLE
    "SRV-HP-A", "SRV-HP-B", "SRV-HP-C" | Get-HPiLOInformation
    Lists iLO firmware information for three servers
     
    #>
    [CmdletBinding(SupportsShouldProcess=$true)]
    Param(
    [Parameter(Mandatory=$false, ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true, Position = 1)][string]$Computername=$env:computername
    )

    Process{

        if ($pscmdlet.ShouldProcess("Retrieve iLO information from server " +$Computername)){
            $MpFirmwares =  Get-WmiObject -Computername $ComputerName -Namespace root\hpq -Query "select * from HP_MPFirmware"
            ForEach ($fw in $MpFirmwares){
                $Mp = Get-WmiObject -Computername $ComputerName -Namespace root\hpq -Query ("ASSOCIATORS OF {HP_MPFirmware.InstanceID='" + $fw.InstanceID + "'} WHERE AssocClass=HP_MPInstalledFirmwareIdentity")

                $OutObject = New-Object System.Object
                $OutObject | Add-Member -type NoteProperty -name ComputerName -value $ComputerName
                $OutObject | Add-Member -type NoteProperty -name ControllerName -value $fw.Name

                Switch ($Mp.HealthState){
                    5 {$stat = "OK"; break}
                    10 {$stat = "Degraded/Warning"; break}
                    20 {$stat = "Major Failure"; break}
                    default {$stat = "Unknown"}
                }
                $OutObject | Add-Member -type NoteProperty -name HealthState -value $stat

                $OutObject | Add-Member -type NoteProperty -name UniqueIdentifier -value $Mp.UniqueIdentifier.Trim()
                $OutObject | Add-Member -type NoteProperty -name Hostname -value $Mp.Hostname
                $OutObject | Add-Member -type NoteProperty -name IPAddress -value $Mp.IPAddress

                Switch ($Mp.NICCondition){
                    2 {$stat = "OK"; break}
                    3 {$stat = "Disabled"; break}
                    4 {$stat = "Not in use"; break}
                    5 {$stat = "Disconnected"; break}
                    6 {$stat = "Failed"; break}
                    default {$stat = "Unknown"}
                }
                $OutObject | Add-Member -type NoteProperty -name NICCondition -value $stat

                $OutObject | Add-Member -type NoteProperty -name FirmwareVersion -value $fw.VersionString
                $OutObject | Add-Member -type NoteProperty -name ReleaseDate -value ($fw.ConvertToDateTime($fw.ReleaseDate))

                Write-Output $OutObject
            }
        }
    }
}

Download hpilo.ps1 here

Example of the output

PS C:\Windows\system32> Import-Module C:\MyPath\hpilo.ps1
PS C:\Windows\system32> Get-HPiLOInformation SRV-HP-A

ComputerName : SRV-HP-A
ControllerName : Integrated Lights Out 4 (iLO4)
HealthState : OK
UniqueIdentifier : ILOCZ123456AB
Hostname : SRV-HP-A-ILO
IPAddress : 192.168.0.201
NICCondition : OK
FirmwareVersion : 1.40
ReleaseDate : 2014-01-14 02:00:00

PS C:\Windows\system32

Gather HP server disk information using PowerShell

2013-05-08 5 comments

I frequently find a need to quickly gather information about the hard drives in my HP Proliant servers. Sometimes I just need to find the model numbers but sometimes I also need information such as serial numbers and firmware versions.
This information is useful when HP releases an urgent firmware upgrade advisory or launches a disk replacement program of which both seem to be quite common lately.

All the needed information is available through WMI on servers that have the HP Insight Management WBEM Providers installed.

Namespace: root\hpq
Classes: HPSA_DiskDrive and it’s associated classes

I wrote the following Powershell function that creates a command that gathers information from servers and returns them as an object that can be sorted, filtered and exported the way you need just as any powershell object.

function Get-HPArrayDisks
{
    <#
    .SYNOPSIS
    Retrieves physical hard disk information for HP servers.

    .DESCRIPTION
    The Get-HPArrayDisks function works through WMI and requires
    that the HP Insight Management WBEM Providers are installed on
    the server that is being quiered.

    .PARAMETER Computername
    The HP server for which the disks should be listed.
    This parameter is optional and if the parameter isn't specified
    the command defaults to local machine.
    First positional parameter.

    .EXAMPLE
    Get-HPArrayDisks
    Lists physical disk information for the local machine

    .EXAMPLE
    Get-HPArrayDisks SRV-HP-A
    Lists physical disk information for server SRV-HP-A

    .EXAMPLE
    "SRV-HP-A", "SRV-HP-B", "SRV-HP-C" | Get-HPArrayDisks
    Lists physical disk information for three servers

    #>
    [CmdletBinding(SupportsShouldProcess=$true)]
    Param(
    [Parameter(Mandatory=$false, ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true, Position = 1)][string]$Computername=$env:computername
    )

    Process{

        if ($pscmdlet.ShouldProcess("List disks on server " +$Computername)){
            $diskdrives =  Get-WmiObject -Computername $ComputerName -Namespace root\hpq -Query "select * from HPSA_DiskDrive"
            ForEach ($disk in $diskdrives){
                $OutObject = New-Object System.Object
                $OutObject | Add-Member -type NoteProperty -name ComputerName -value $ComputerName
                $OutObject | Add-Member -type NoteProperty -name Slot -value $disk.ElementName
                $OutObject | Add-Member -type NoteProperty -name Interface -value $disk.Description
                $OutObject | Add-Member -type NoteProperty -name RotationalSpeed -value $disk.DriveRotationalSpeed

                $drivePhys = Get-WmiObject -Computername $ComputerName -Namespace root\hpq -Query ("ASSOCIATORS OF {HPSA_DiskDrive.CreationClassName='HPSA_DiskDrive',DeviceID='" + $disk.DeviceID + "',SystemCreationClassName='" + $disk.SystemCreationClassName + "',SystemName='" + $disk.SystemName + "'} WHERE AssocClass=HPSA_DiskPhysicalPackageDiskDrive")
                $OutObject | Add-Member -type NoteProperty -name Model -value $drivePhys.Model
                $OutObject | Add-Member -type NoteProperty -name SerialNumber -value $drivePhys.SerialNumber.trim()

                $driveFW = Get-WmiObject -Computername $ComputerName -Namespace root\hpq -Query ("ASSOCIATORS OF {HPSA_DiskDrive.CreationClassName='HPSA_DiskDrive',DeviceID='" + $disk.DeviceID + "',SystemCreationClassName='" + $disk.SystemCreationClassName + "',SystemName='" + $disk.SystemName + "'} WHERE AssocClass=HPSA_DiskDriveDiskDriveFirmware")
                $OutObject | Add-Member -type NoteProperty -name FirmwareVersion -value $driveFW.VersionString.trim()

                $driveStorage = Get-WmiObject -Computername $ComputerName -Namespace root\hpq -Query ("ASSOCIATORS OF {HPSA_DiskDrive.CreationClassName='HPSA_DiskDrive',DeviceID='" + $disk.DeviceID + "',SystemCreationClassName='" + $disk.SystemCreationClassName + "',SystemName='" + $disk.SystemName + "'} WHERE AssocClass=HPSA_DiskDriveStorageExtent")
                $OutObject | Add-Member -type NoteProperty -name SizeInGigabytes -value ([math]::round(($driveStorage.BlockSize * $driveStorage.NumberOfBlocks) / 1000000000))
                $OutObject | Add-Member -type NoteProperty -name PowerOnHours -value $driveStorage.TotalPowerOnHours

                Write-Output $OutObject
            }
        }
    }
}

Download hpdisks.ps1 and import it in your powershell session using the command

Import-Module hpdisks.ps1

When you have imported the module you can get help about it’s command just like you would with any other powershell command.

Get-Help Get-HPArrayDisks -detailed

Whatever you pipe into the Get-HPArrayDisks command will be treated as a server name and it will attempt to gather HP disk information from the server.
You can pipe names from the commnd line, from other commands or from text files using the Get-Contents command. Some quick examples:

Get-HPArrayDisks myservername

"myserver1","myserver2" | Get-HPArrayDisks | ft computername, slot, model, serialnumber

Get-Content allmyservers.txt | Sort-Object | Get-HPArrayDisks | Export-Csv -path myserverdisks.csv -NoTypeInformation

You may also want to read
Gather HP iLO information using PowerShell

Using Rotary Encoders with Arduino

2012-11-01 8 comments

Rot enc

Introduction

There seems to be a lot of confusion among Arduino beginners about how rotary encoders work and how you best use them with Arduino.

I will try to explain a little bit and show some examples to get you started. The example circuit and the code should be enough to get you started if you don’t want to read the other mumbo jumbo.

What is a rotary encoder?

A rotary encoder is electromechanical component with a shaft. Shaft rotation is recorded and converted to electrical pulses that tell in which direction the shaft is rotating. The shaft has unlimited 360 degree rotation.

A rotary encoder can tell you:

  • That the shaft is rotating
  • How much it is rotating
  • In which direction it is rotating

A rotary encoder can NOT tell you:

  • The position or the orientation of the shaft (knobs with indicators are useless)

Protocol

I’m not going to get into the inner workings of rotary encoders but let’s mention how a simple rotary encoder commuinicate.

There are two output pins (called A and B) that are used to for reading rotation and a third pin that normally connects to GND.
When you turn the encoder, switches inside the encoder opens and closes to turn the outputs HIGH or LOW.

The rotary encoders “speak” gray code which means that the encoder pins are cycling through a predetermined pattern of HIGH and LOW signals.
When you turn the shaft of the encoder clockwise the signal on the encoder pins loops through a pattern like this:

A B
0 0
1 0
1 1
0 1

If we can detect that the pins are changing we know that the shaft is rotating. How often the pulses change tells us how fast it’s turning. How many times it has changed tells us how far it has been turned etc.
When you turn the shaft counter-clockwise it loops through the sequence backwards and that’s how we know in which direction it’s rotating.
Most shaft encoders have fixed stops or “stability positions” so that the shaft stops or clicks at every 0pen-0pen or closed-closed position or both.
Your datasheet will reveal which type you have. There will be a pulse diagram in of the pulses at clockwise operation that looks something like one of the below pictures. The dotted lines indicate shaft stops.

Stops at every closed position

Stops at both closed and open position

Bounce

Cheap encoders are known to cause a lot of contact bounce so you will need to debounce the signal from the encoders. We will use interrupts on the Arduino for detecting encoder rotation so it’s easier to debounce the encoder with hardware and get nice clean pulses than to try and debounce using software delay.

I have tried some variants and settled with 47nF ceramic capacitors and Schmitt Triggers on the outputs. I have also connected the shield on my encoders to ground through another 47nF ceramic capacitor.

Example circuit

This is how to debounce and connect an encoder to the Arduino:

Example circuit with debounced rotary encoder connected to Arduino

I connect encoder output A to D2 on the Arduino because D2 is an interrupt pin (interrupt 0) which we will use to detect rotation.
Output B can go to any digital pin. I use pin 4 in the example.

If you want to connect another encoder to the same Arduino, use pin D3 for output A on that encoder and enable interrupt 1.

I you have an Arduino Mega you can use four additional interrupts on pins D18, D19, D20, D21.

Arduino sketch

This is an example that uses one interrupt to detect rotation on a rotary encoder which only stops when it’s in closed position.
If you have an encoder that stops at both closed and open you will have to turn your encoder two clicks to register a turn. Correct this by changing the interrupt type from RISING to CHANGE sol that an interrupt is triggered on every change.

int pinA = 2; //Encoder pin A connects to interrupt 0 (D2)
int pinB = 4; //Encoder pin B connects to D4
int iValue = 0; //A variable that will be increased or decreased
                //when we turn the encoder

void setup() {
  Serial.begin(9600);
  
  pinMode(pinA, INPUT);  
  pinMode(pinB, INPUT);
  
  // Enable interrupt on encoder pin A
  // Trigger at RISING if your encoder stops (clicks) only at high pulse
  // Trigger at CHANGE if your encoder stops (clicks) at both high and low
  // positions or if it has no stops
  attachInterrupt(0, encoderClick, RISING);
}


void loop() {
  // continuously print the value to see how it changes
  Serial.println(iValue);
  delay(200);
}


void encoderClick(){
  // encoder must have turned one click because interrupt 0 was triggered
  // read value from both encoder pins
  int valA = digitalRead(pinA);
  int valB = digitalRead(pinB);
  
  // compare pins to determine in which direction encoder was turned
  if (valA != valB){
      // pinA just changed but pinB had not yet changed
      // Direction must be clockwise if A changes before B
      iValue++;
  }
  else{
      // pinA just changed and pinB had already done so.
      // Direction must be counter-clockwise if B changes before A
      iValue--;
  }
}

Download the sketch here

Arduino based remote control for electric door

2012-10-14 Leave a comment

I recently built a replacement remote control system for an electric garage door after the old remote had given up for the babillionth time.
I’m sure the old one would have been possible to repair once again but it was 35 years old and not much fun.

Old receiver and transmitter

Pictures from left to right:

  1. The front of the old receiver with an indoor open/close button.
  2. Inside of the receiver. Nice and clean and very analog electronic fossil.
  3. The guts from the old transmitter. The case that this used to sit in was removed and reused for the new transmitter.
  4. Backside of the old receiver. The label reads “Chambron Radio Control Model C-2216″. There’s also a letter to Mr. Serviceman.
    Who knows anything about this thing?

The motor to the door is controlled by shorting two cables and thereby closing a circuit. A short pulse is enough to start the motor. If the door is closed it will open. If it’s already open, the door will close. If the motor is moving when the pulse arrives it will change direction.

The new solution

433MHz transmitter (left) and receiver (right)

I wanted a new solution that would be a bit more secure and hopefully have the same range as the old one had and I wanted to base it on an ATmega328P with an Arduino core and some really cheap 433Mhz ASK modulated RX/TX modules that can be found everywhere on eBay.

I have used these RF modules before and know they have a decent range and can penetrate doors, windows and even walls in some cases. They are also easy to interface with using the VirtualWire library for Arduino. The downside is that they only work in one direction.

Even if it wasn’t really necessary in this case I wanted to implement some kind of security or obfuscation of the commands sent over the air. This is something of a challenge with a system that only communicates in one direction since it’s not possible to use a challenge/response based protocol and the Arduino doesn’t have storage enough to store predefined passcode sequenced.
This was what I wanted:

  • Use one time passcodes so that simple sniffing wouldn’t be enough to grant access forever
  • Not have to store the passcode sequence in advance
  • Generate passcodes that don’t seem to follow a clear pattern to complicate analysis of the commands

The protocol I ended up with works like this:

  • The receiver and transmitter are paired to use a sequence of numbers starting at a large random number that is decided by the transmitter. The number is sent to the receiver during the pairing process which more or less is a one time operation.
  • When the transmitter wants to send a open/close command to the door it increases the number by one and hashes the number using MD5
  • The receiver knows which number it expects and when it receives a hash from the transmitter it hashes the expected number and compares the resulting hash with the received hash. If the hash is correct it sends a pulse to the door so that it will be opened or closed. The next expected passcode is simply the last passcode +1.
  • If the hashes didn’t match it increases the expected number one by one and creates new hashes to compare with up to fifty times to allow for missed passcodes that might have been sent when the transmitter was out of range or similar. This gives us a sliding window of 50 valid passcodes. As soon as a matching passcode is found, the receiver is synced with the number received and a pulse is sent to the door.
  • The current numbers are stored in the ATmega EEPROM in both transmitter and receiver.

Hardware

The new transmitter and receiver waiting for installation

I’m using ATmega328P (DIP-28) for both transmitter and receiver. I would probably have used an ATtiny for the transmitter to try and reduce size if it wasn’t for the MD5 library that adds a whopping 12KB to the  binary sketch size making the total sizes around 18KB for both receiver and transmitter.

Transmitter

Since I couldn’t find a suitable pocket size case for the transmitter and a good matching push button I reused the old one. The green LED to the left of the battery pack was added for troubleshooting reasons during installation but I never drilled a hole in the case for that LED due to lack of space.
The button at the top of the PCB is the open/close button. There’s another button on the back side of the PCB that is used during pairing.
The blue cable that is routed from the RF module and around the PCB is the antenna which is a piece of wire that is cut to a quarter of the wavelength equaling 17.3cm.
34.5cm or 69.1cm would also have been OK if there was space enough in the box but looping the antenna round and round in several loops close to each other would not do much good.
The new transmitter resting in the case from the old transmitter (lid open)
The ATmega in the transmitter is running on the internal oscillator at 8MHz to allow the supply voltage to drop to 3.0V. The 16MHz external crystal in the picture is still there but was only used during prototyping. I’m also disabling brownout detection on the ATmega for maximum power savings during power down. The fuses I’m using for setting the clock source to internal oscillator @ 8MHz and disable brownout detection are:
Low Fuses: E2
High Fuses: DA
Extended Fuses: 07

The board definition I put in boards.txt is:

##############################################################
328_8.name=ATmega328, 8MHz Internal OSC, BOD disabled
328_8.upload.protocol=arduino
328_8.upload.maximum_size=30720
328_8.upload.speed=57600
328_8.bootloader.low_fuses=0xE2
328_8.bootloader.high_fuses=0xDA
328_8.bootloader.extended_fuses=0x07
328_8.bootloader.path=atmega
328_8.bootloader.file=ATmegaBOOT_168_atmega328_pro_8MHz.hex
328_8.bootloader.unlock_bits=0x3F
328_8.bootloader.lock_bits=0x0F
328_8.build.mcu=atmega328p
328_8.build.f_cpu=8000000L
328_8.build.core=arduino
328_8.build.variant=standard
##############################################################

This configuration makes it possible to use a bootloader if desired but I upload the sketch to the chip using an ISP programmer so I don’t have a need for a bootloader in this case.
For other applications using 8MHz internal oscillator, I have always used the ATmegaBOOT bootloader because I’ve not had any luck compiling the Optiboot for this. If someone has a Makefile that is generating a working Optiboot image for 8MHz internal, please let me know in the comments.

Receiver

I got rid of the old receiver case because it was made of thick metal and I was afraid that it could affect the reception in a negative way but it would probably have been OK due to the external antenna. There are plenty of boxes suitable for the transmitter but I settled with a minimal, cheap plastic box for electric installations. I should have picked a bigger one because this was a pretty tight fit.
The connector on the right side is the DC plug for the power supply.
To the left is an LED that flashes during pairing and is lit during reception of data. The button on the same side as the LED is the pairing button.

The antenna which is rolled up outside the box in this picture should normally be stretched out. It consists of 69.1 cm of wire soldered to the antenna connection on the RF module.

The new receiver box with lid, sides and terminals removed

Motor connection

I send the pulses for the motor by running the two wires from the motor through a relay inside the receiver. I pull the relay for a short time using an output on the Arduino whenever a matching hash has been received.
I also added an external momentary push button mounted on the wall that shorts the same two wires so that the door can be opened and closed from the inside without using the remote control.

Receiver installed in garage with indoor open/close momentary button attached

Performance

How well does this solution work?

Range

50 metres (with the transmitter in a car, new batteries in the transmitter and the receive inside the closed garage door)
This is more than enough and just as good as the old system ever was.

Power consumption: Receiver

Approx. 30mA @ 5V
I haven’t done anything to reduce the power consumption on the receiver since it will be powered by a DC adapter.

Power consumption: Transmitter

The transmitter runs straight from three AA batteries that should (until depleted) keep the voltage over  3.0V at all times which is what the RF transmitter module needs to work properly. The maximum 4.5V is also perfectly fine for both RF module and ATmega.
Current during transmission (basically as long as the button is pressed) is ~25mA @ 4.5V
During powerdown which is the normal condition when no button is pressed, the current drops to 0.1uA
This is as low as it gets with an ATmega328P and to achieve this brownout detection has to be disabled.

Possible future improvements

  • Add possibility to use more than one transmitter.
  • Prevent brute force attacks by adding growing delays after incorrect codes
  • Etch custom PCBs, possibly using SMT components for transmitter
  • Add more decoupling capacitors, at least for the receiver.
  • Shrink the transmitter by creating better and smaller case and PCB for the transmitter
  • Fix bugs
  • Well… let’s see how it works

References

Code

Download both sketches and all libraries in one zip file: Code

Schematics

The schemattics for both units in PNG format: Transmitter and Receiver

Video

Uni-T UT61D for Linux

2012-05-10 7 comments

UT61D

I recenetly purchased a digital multimeter called Uni-T UT61D.
It’s a fairly nice model with decent precision and a build quality that feels good. It’s auto-ranging and measures a little bit of everything. It’s a real improvement to my old basic device and this one also has auto power-off which was a requirement for my new DMM. I’m so tired of putting new batteries in the old one whenever I forget to turn it off (which is all the time). It’s also good to have access to two DMM’s at the same time.

The UT61D has also got a serial interface that connects the DMM to a computer via RS232 or USB. This seemed like a cool feature but of course there were no drivers or applications included for Linux so I started to scan the web for solutions. I could have used a Windows computer but where’s the challenge in that?
Some guys have figured out and written tools for the UT61A, UT61B, UT61C & UT61E which are similar but none seemed to have done much work with the 61D.

he2325u printing raw data from the UT61D

he2325u printing raw data from the UT61D

HE2325U

I could find one driver that after some tweaking extracted data over USB. It was the he2325u by Rainer Wetzel.
His package also included a parser and a plotter that could be used to process the raw data coming out of the he2325u software.
They didn’t work with the 61D because they were written for 61E which has an entirely different protocol.

However the protocol for the B, C, D models is identical. I found a few apps that should work with these models but they were all using RS232 and not the USB HID connection that I wanted to use.

dmmut61b

After going through my options I decided to modify one of them so that instead of reading data from RS232 it would read from stdin so that I could pipe data from he2325u to it and use it as a pure parser. The one I settled with was a perl script called dmmut61b which was written by H.P. Stroebel. It had a nice feature set and was easy to modify. Mr Stroebel was also helpful during later troubleshooting because unfortunately it turned out that I was loosing some information somewhere and in the end that turned out to be because the he2325u software wasn’t fully compatible with the B,C,D models protocol. It was masking out bits that contained the micro prefix for μF and μA so they turned up like F and A instead.
With that fixed it finally worked as I wanted.

dmmut61bcd parsing data from he2325u

dmmut61bcd parsing data from he2325u

I have collected modified tools, scripts and source code in an archive in case anyone else needs it: ut61d.zip
The he2325u binary in that archive is my modified version that is working well on my 32-bit Ubuntu 12.04 setup.

Resources

Protocols documented by Henrik Haftmann
dmm61b by H.P. Stroebel
he2325u by Rainer Wetzel
Uni-Trend documentation
How to get the USB PID device running in Linux

Using USBtinyISP with homebrew Arduinos in Linux

2011-11-22 5 comments

I had some problems getting my cheap eBay USBtinyISP programmer clone to work in Ubuntu so I thought I’d share some hints or at least write them down for the next time I need them.
Some of the information in this post applies only to Linux systems and I haven’t used it in Windows so I don’t know how that works.

Cheap USBtinyISP clone connected to a breadboard "Arduino"

Cheap USBtinyISP clone connected to a breadboard “Arduino”

Connection

If you’re going to burn an Arduino bootloader on a standalone chip for example on a breadboard you normally don’t have any ISP headers available and therefore have to connect the wires by yourself. It’s of course possible to put the chip into a real Arduino board and plug into the ICSP header on the Arduino but I don’t like to jerk chips in and out of my Arduino sockets all the time because it’s just a matter of time before something breaks.
I’m going to assume we’re using a breadboard to hook up the chip being programmed in this example.

It doesn’t matter which of the ICSP connectors you choose to connect to your breadboard. None of them are suitable for breadboard connection anyway since they are both 2-row connectors. There are ICSP breakout boards available that make them easier to use on breadboards but we’re not going to use one this time.
The fastest and cheapest (and probably ugliest) way is to simply connect jumper wires from the ICSP connector to the breadboard.

This is the 6-pin ICSP connector pictured from above so you will have to think a bit when you look at the connector from the bottom side where you insert the jumper wires.

6-pin ICSP connector pinout

6-pin ICSP connector pinout

The 10-pin connectors are a bit different but they have these six connectors too and they are all we need. Google up a picture of the 10-pin connector if you need to use that.

The ICSP connectors are wired to the SPI pins on the ATmega. Connect the six pins according to the following table:

Pin Connect to
MISO  ATmega328 Pin 18 (Arduino D12)
VCC 5V on your board
SCK ATmega328 pin 19 (Arduino D13)
MOSI ATmega328 pin 17 (Arduino D11)
RST ATmega328 pin 1 (directly to pin 1 without 0.1 uF cap)
GND GND on your board

In addition to this the ATmega needs to be hooked up to Vcc and GND and needs an external 16MHz crystal.
The programmers often has a jumper for supply power. With the jumper installed the programmer will supply power to your circuit so you don’t need to install an external power source.

Note:
I ran into problems whenever I had something else connected to any of the four SPI pins. For example I’m used to having a led connected immediately to D13 for debugging reasons (compatible with the built in LED on Arduino boards). I didn’t get any response from the ATmega when trying to program it or querying  it using avrdude. My guess is that my LED pulled down the the clock pulses. Removing my LED solved the problem anyway. This obviously isn’t a problem with the built in LED on the Arduino board and I don’t know exactly how they hooked it up but I’m pretty sure they didn’t connect it right onto D13 so if anyone has a recommendation or knows the trick that allows these pins to be used for other things and still be able to program the chip, post it in the comments.

Starting up

It’s now time to connect the programmer to the USB port, fire up the Arduino IDE and get burning.

The USBtinyISP will not show up as a serial port in the Arduino IDE when you connect it and it can not be used to send and receive serial data so don’t bother.

Burning bootloaders

You could try burning a bootloader from the Arduino IDE at this point by selecting a board from the boards menu and selecting Burn Bootloader -> w/ USBtinyISP.
Unless you’re going to use the chip on a Uno board or with some ATmega8U2 based USB-adapter you most likely want to choose Duemilanove or Nano w/ ATmega328. That way you can use an FTDI adapter or cable to upload sketches to it later.

Uploading sketches

You can also use the programmer as an interface for uploading Arduino sketches but that is done without utilizing an Arduino bootloader and you won’t be able to upload any more sketches to that chip using an FTDI or similar interface until you burn a new Arduino bootloader onto the chip.

To create the interface for uploading sketches using the USBtinyISP you need to add the following board definition to arduino/hardware/boards.txt:

##############################################################

usbtinyisp328.name=ATmega328 w/ USBtinyISP

usbtinyisp328.upload.using=usbtinyisp
usbtinyisp328.upload.maximum_size=32768
usbtinyisp328.upload.speed=57600

usbtinyisp328.build.mcu=atmega328p
usbtinyisp328.build.f_cpu=16000000L
usbtinyisp328.build.core=arduino

Arduino 1.0 update:
Adding this configuration to boards.txt is no longer necessary in Arduino 1.0 since there is a new built-in function called Upload Using Programmer.

You might have luck in changing the upload speed but in my case increasing it further didn’t affect upload speed at all. My programmer burns at a speed of aproximately 1KByte/s.

After you restart Arduino the new definition will be listed as a board in the Board configuration menu. Select the board named ATmega328 w/ USBtinyISP and hit upload and the sketch will be burned to your chip.

This is useful if you want to do in system programming and don’t have an FTDI cable. When you build a permanent project that you want to be able to re-program later you just add ICSP header pins to your circuit (or a socket for the ATmega).
This is what ISP programmers are made for.

Sketches uploaded using this configuration will overwrite whatever Arduino bootloader you have on your chip and can therefore use all 32768 bytes instead of the normal 32256 bytes (UNO) or 30720 bytes (Duemilanove). That doesn’t sound like much and it isn’t all that much either but if you would use a smaller chip than the ATmega328 with let’s say 4KB of flash those bytes make up a big percentage of the total size.

Linux Permissions

To avoid having to run the Arduino IDE or avrdude as root you need to grant users the right to use the device. This is accomplished by creating a udev rule. This is how it’s done in Ubuntu:

Create the file /etc/udev/rules.d/usbtinyisp.rules containing this single row:
SUBSYSTEM==”usb”, SYSFS{idVendor}==”1781″, SYSFS{idProduct}==”0c9f”, GROUP=”adm”, MODE=”0666″

Restart udev using ‘restart udev’ after saving the file.

Ubunti 12.04 update:
After upgrading to Ubuntu 12.04 LTS the SYSFS keyword didn’t work for me anymore due to some change in udev. The following rule works after the upgrade:
SUBSYSTEM==”usb”, ATTR{idVendor}==”1781″, ATTR{idProduct}==”0c9f”, GROUP=”adm”, MODE=”0666″

Troubleshooting

Use avrdude to diagnose any errors.
To verify the connection between computer – programmer – microcontroller run the following command:

‘avrdude -c usbtiny -p m328p’

The output from the command should tell whether your setup works or give a clue to why it doesn’t. These are some examples with explanations:

avrdude: AVR device initialized and ready to accept instructions
Reading | ################################################## | 100% 0.01s
avrdude: Device signature = 0x1e950f
avrdude: safemode: Fuses OK
avrdude done. Thank you.
This is what you’re aiming for. It’s a good respons that means you just talked to the ATmega and it’s begging to be programmed.

avrdude: Error: Could not find USBtiny device (0x1781/0xc9f)
Can’t find the USBtinyISP at all. Is it connected properly?

avrdude: initialization failed, rc=-1
Double check connections and try again, or use -F to override
this check.
Avrdude managed to talk to the USBtinyISP but could not detect your chip. Check the connections to your ATmega again.

avrdude: error: usbtiny_transmit: error sending control message: Operation not permitted
In Linux this means  that you probably need more permissions. Read the Linux Permissions section above.

For the lazy or frequent burner

If you don’t want to bother about putting ICSP headers on every single stripboard but still want to be able to program your chips with ease, build one of these:

USBtinyISP with ZIFduino

USBtinyISP with ZIFduino

This adapter is just a board with a ZIF-socket, 6-pin ICSP header and a fixed 16MHz crystal.
Perfect for bootloading chips or  reprogramming chips used in permanent installations.
16 MHz chips that is…

Breadboard Arduinos and Sparkfun’s FTDI Basic Breakout

2011-11-19 4 comments
Sparkfun FTDI Basic Breakout

The FTDI Basic Breakout from Sparkfun

I recently purchased one of these breakout boards from Sparkfun. I bought the 5V version because I want to power an ATmega328 over the USB connection on the board.

This is the procedure I use to connect and upload sketches to a breadboard Arduino from the Arduino IDE in Linux:

First of all, the ATmega328 chips that I’m using are already bootloaded using the Duemilanove bootloader. (Duemilanove w/ ATmega328 in the boards menu).
The ATmega needs to be hooked up with VCC & GND connectors (will be powered from FTDI board), an external 16MHz Crystal and a 0.1uF capacitor on pin 1 for auto-reset. A pull-up resistor on pin 1 is recommended.

Arduino on a breadboard

Arduino on a breadboard

Now add the breakout board to the breadbord and hock it up like this:

  • Connect the DTR pin to pin 1 on the ATmega through the 0.1uF capacitor.
  • Connect the RX pin to pin 3 on the ATmega (TX)
  • Connect the TX pin to pin 2 on the ATmega (RX)
  • Connect the 5V pin to the 5V rail of the board to supply the board with power from the USB interface.
  • Connect the GND pin to the GND rail of the board
Arduino on breadboard with FTDI Basic Breakout

Arduino on breadboard with FTDI Basic Breakout

Connect the USB cable and fire up the IDE.
There should now be a serial port called ttyUSBx. Select it.

From the boards menu, select Arduino Duemilanove or Nano w/ ATmega328

It should now be possible to upload sketches.

Follow

Get every new post delivered to your Inbox.