Amazon Banner

Thursday, October 24, 2013

Deploying Installshield package via SCCM fails, Return Code -3

I recently ran into an issue installing the driver package for some new Interlink "Epad" signature pads we got in at work.  The instructions from the readme file for unattended installs matched the typical method for InstallShield packages:
  1. Run the installer with additional parameters to record the install and create a response file.  Example: "setup.exe /r /f1c:\temp\setup.iss"
  2. Copy the setup.exe and setup.iss files to the computer where the software needs to be installed.  
  3. On the target computer, run "setup.exe /s /f1setup.iss /v/qn"
In theory, this should silently run the installer, using the same responses provided when creating the response file in step 1.  In my case, this worked perfectly.  As long as I was manually running the command in step3 from an administrative command prompt.  When I tried deploying this as an application from system center, using the same command line and the same response file, the installation failed with a return code of "-3". 

Since the command works fine when I run it manually, I decided it had to be a problem of the different context in which configmgr was running the installer.  Configmgr was running the package as system, not as a user.  

When the InstallShield package executes, the first thing it does is extract files into a temporary location.  If I run it manually, those files are placed in c:\users\\appdata\local\temp\ - but it can't use the same path when running in the system context.  I was able to work around this by adding a "/b" parameter, in which is the directory where I want the setup files extracted to.  The final command line used for the application in SCCM looked like this:
"setup.exe" /s /f1setup.iss /bc:\swsetup\ /v/qn
Using that syntax, the application installed successfully from ConfigMgr.  Hopefully this information will be useful to others who might run into the same error. 

Tuesday, July 2, 2013

SCCM 2012 OSD Refresh Error: "FAILURE (5456): Unable to determine Destination Disk, Partition, and/or Drive."

I recently modified our SCCM (MDT Integrated) OSD task sequence so that we could also use the refresh deployment type.  One of the requirements for our refresh was that the hard drives be re-partitioned and formatted, just as they would if it were a "New Computer" deployment type.  To accomplish this, I copied the "Format Disk" group from the "New Computer Only" section of the task sequence into the "Refresh Only" section.  

When testing the refresh deployment, the process started off smoothly, but eventually the task sequence restarted the computer.  When the computer tried to boot back up, there was no OS on the drive. The only clue as to the cause was found in the bdd.log file: 

FAILURE (5456): Unable to determine Destination Disk, Partition, and/or Drive.

The task sequence attempts to back up the original drive to an image before re-installing the OS.  Since I had added the format steps under "Refresh Only" (which is above "Backup" in the task sequence), the drive was already wiped before the backup step tried to run.  In my case, I don't want a full backup of the computer anyway, so disabling the backup step resolved the issue.  If you do want a full backup before the drive is wiped, moving the "backup" step up into or above the "refresh only" group would probably solve this issue. 

Monday, March 18, 2013

Cacheberry Pi

As an avid Geocacher, when I was thinking of what to do with my Raspberry Pi, I couldn't help but wonder what geocaching related devices I could make.  I considered building a geocache that had some kind of electronics, controlled by the Pi, but decided that powering the Pi long term would be an issue.  I searched for other ideas online, and came across a video of the Cacheberry Pi project, by Jeff Clement.  The perfect mix of geocaching, electronics, and programming, I had found my first project!

The Cacheberry Pi is designed to be used in the car.  Place the small box on the dashboard, connect it to power, and while you're driving, the Raspberry Pi will search a pre-loaded database of geocaches for the nearest cache in the direction you're travelling.  This is different from most GPS receivers or applications because it searches only a narrow area ahead, and will not return caches that you've already passed by.

I've spent the last few weeks getting it working.  I used some slightly different hardware from the original, so it wasn't quite as simple as dropping his image onto my Pi and running it.  Here's what I used:
The Cacheberry-Pi displays a dashboard screen when no
nearby caches are found.
Getting the Raspberry Pi up and running was easy.  Getting the other hardware working right took a little bit of time.  The LCD that I used didn't work with the lcdproc driver included in the original version of the Cacheberry Pi.  I struggled for a while to get the lcd working right.  For more info on that, and to download the modified driver if you need it, see my previous post on the subject here.

The GPS module I used doesn't connect via USB, but instead connects directly to the GPIO pins on the Raspberry Pi and communicates via serial.  By default, the serial port on the Raspberry Pi is set up as a serial console, which must be disabled before it can be used by the GPS.  This can be done by making small changes in 2 files.

In /etc/inittab scroll to the end of the document, where you should add a # sign before this line:
T0:23:respawn:/sbin/getty -L ttyAMA0 115200 vt100
Next, edit /boot/cmdline.txt - This file is just one long line of text.  Find and remove the following from that line:
console=ttyAMA0,115200 kgdboc=ttyAMA0,115200

GPSD must also be reconfigured for the serial port instead of the USB. To do this, run:
sudo dpkg-reconfigure gpsd
This will start a wizard to configure settings for gpsd.  Set gpsd to run automatically at startup, then accept the default settings on each screen until prompted for the port that the gps unit is connected to.  Enter the following in the port field:
I've added an extra LED to my cacheberry pi, which is connected directly to the LED pin on the +Adafruit GPS unit.  This makes it easy to tell whether the GPS has a signal lock yet.  The other LED is controlled by the python code and activates based on the cache search pattern and distance.

I've also forked the Cacheberry Pi project on github and made a few changes to the code.  I added some missing steps to the instructions in the readme, to make it easier for others to reproduce the project. I've added configuration settings to display measurements in Metric or Imperial units, localize the time displayed on screen, adjust the scroll speed of geocache data on screen, changed what information about a geocache is displayed on the screen and how it's formatted, and made a few other small changes.  I hope these changes can be of help to someone else who is inspired by Mr Clement's project and wants to give it a try.

The updated code with these changes can be found here github.

Still on my to-do list for this project:

  • Adjust the behavior and triggers for the software controlled LED
  • Add a push button or keypad to allow simple interaction with the Cacheberry-Pi
  • Add a method for initiating a safe shutdown of the OS
  • Add some kind of backup power system which will kick in when the vehicle power is turned off, triggering a safe shutdown of the Pi's OS and powering the Pi long enough for that shutdown to complete. 
  • ???

Saturday, February 2, 2013

Using a 16x2 LCD with i2c on the Raspberry Pi

I got a Raspberry Pi for Christmas, and have been playing with it ever since. For one project, I needed to display a couple of lines of text. I ordered a 16 Character x 2 Line LCD display based on an hd44780 compatible controller. From what I had read, I wanted one with an i2c i/o expander. By using i2c, the lcd can be controlled using just 4 GPIO pins from the Raspberry Pi instead of 8. I ended up ordering the SainSmart IIC LCD1602 Display from amazon for just $12.

When I received the LCD, I hooked it up to my Pi and tried using it with a tutorial I found on the raspberry pi blog. The tutorial I was following mentioned that some of the i2c expansion 'backpack' boards connected the i2c chip's pins to the lcd's pins in a different way than others, and that the code has to be modified to use it with other versions.  When I couldn't get it working, I looked through the 'documentation' sainsmart offered for download on their website and in the product description on amazon. Unfortunately, the documentation was basically just some sample code for arduino. (As it turns out, the sample arduino code didn't even work.  It was written for an old, pre 1.0 version of the arduino IDE.) I contacted sainsmart support to ask for any further documentation available and a schematic of the i2c expander board, but the best they could do is point me to a post on someone's blog about using an i2c controlled lcd with the Raspberry Pi. After examining the path of traces on the backpack board, I was able to map out which pins of the i/o expander chip were connected to which pins of the lcd:

P0       RS
P1       RW
P2       EN
P3       BL
P4       D4
P5       D5
P6       D6
P7       D7
Armed with this information, I was able to get assistance from the lcdproc help to modify the hd44780-i2c driver used by lcdproc.  Since I had seen many posts from others with the same problem, I wanted to share the solution.  Here is the patch code code that I used to modify the hd44780 driver:

Index: server/drivers/hd44780-i2c.c =================================================================== RCS file: /cvsroot/lcdproc/lcdproc/server/drivers/hd44780-i2c.c,v retrieving revision 1.14 diff -u -r1.14 hd44780-i2c.c --- server/drivers/hd44780-i2c.c 30 Oct 2010 18:04:21 -0000 1.14 +++ server/drivers/hd44780-i2c.c 27 Jan 2013 14:39:31 -0000 @@ -76,10 +85,10 @@ void i2c_HD44780_backlight(PrivateData *p, unsigned char state); void i2c_HD44780_close(PrivateData *p); -#define RS 0x10 -#define RW 0x20 -#define EN 0x40 -#define BL 0x80 +#define RS 0x01 +#define RW 0x02 +#define EN 0x04 +#define BL 0x08 // note that the above bits are all meant for the data port of PCF8574 #define I2C_ADDR_MASK 0x7f @@ -168,43 +214,43 @@ // powerup the lcd now /* We'll now send 0x03 a couple of times, * which is in fact (FUNCSET | IF_8BIT) >> 4 */ - i2c_out(p, 0x03); + i2c_out(p, 0x30); if (p->delayBus) hd44780_functions->uPause(p, 1); - i2c_out(p, enableLines | 0x03); + i2c_out(p, enableLines | 0x30); if (p->delayBus) hd44780_functions->uPause(p, 1); - i2c_out(p, 0x03); + i2c_out(p, 0x30); hd44780_functions->uPause(p, 15000); - i2c_out(p, enableLines | 0x03); + i2c_out(p, enableLines | 0x30); if (p->delayBus) hd44780_functions->uPause(p, 1); - i2c_out(p, 0x03); + i2c_out(p, 0x30); hd44780_functions->uPause(p, 5000); - i2c_out(p, enableLines | 0x03); + i2c_out(p, enableLines | 0x30); if (p->delayBus) hd44780_functions->uPause(p, 1); - i2c_out(p, 0x03); + i2c_out(p, 0x30); hd44780_functions->uPause(p, 100); - i2c_out(p, enableLines | 0x03); + i2c_out(p, enableLines | 0x30); if (p->delayBus) hd44780_functions->uPause(p, 1); - i2c_out(p, 0x03); + i2c_out(p, 0x30); hd44780_functions->uPause(p, 100); // now in 8-bit mode... set 4-bit mode - i2c_out(p, 0x02); + i2c_out(p, 0x20); if (p->delayBus) hd44780_functions->uPause(p, 1); - i2c_out(p, enableLines | 0x02); + i2c_out(p, enableLines | 0x20); if (p->delayBus) hd44780_functions->uPause(p, 1); - i2c_out(p, 0x02); + i2c_out(p, 0x20); hd44780_functions->uPause(p, 100); // Set up two-line, small character (5x8) mode @@ -240,8 +284,8 @@ i2c_HD44780_senddata(PrivateData *p, unsigned char displayID, unsigned char flags, unsigned char ch) { unsigned char enableLines = 0, portControl = 0; - unsigned char h = (ch >> 4) & 0x0f; // high and low nibbles - unsigned char l = ch & 0x0f; + unsigned char h = ch & 0xf0; // high and low nibbles + unsigned char l = (ch << 4) & 0xf0; if (flags == RS_INSTR) portControl = 0; @@ -277,7 +321,7 @@ */ void i2c_HD44780_backlight(PrivateData *p, unsigned char state) { - p->backlight_bit = ((!p->have_backlight||state) ? 0 : BL); + p->backlight_bit = ((p->have_backlight && state) ? BL : 0); i2c_out(p, p->backlight_bit); }

A copy of the modified source code and a compiled, ready to use, copy of the driver file can be downloaded here.

The sainsmart backpack board seems to be a clone of a similar board made by DFROBOT and others, so if your i2c backpack matches the pinouts I listed above, give the modified driver for lcdproc a try.

I hope this post is able to save others from going through the trouble I did to get this LCD working.

Hello World

Recently, I've found myself wanting to share the occasional information related to my work and hobbies. Thus, a new blog.