Archive for the ‘Electronic Projects’ Category:
13 Apr
Kiln Project part II
I’m still thinking about what to do… but I LIKE the PID solution. I also like how PID controllers usually display both SETPOINT and CURRENT value. So, with that in mind, I set about designing a dual display board (in a design that I can use a single 4 digit display board later).
It uses the HP 5082-7300 and HDSP 0960 series displays that I have had in my parts collection going on like 20 years or more.
So, just a little more code for the controller (adding Encoder and Displays) and I should be ready to fire up the KILN… with some nice temperature control and visual feedback.
I ended up with near perfect toner transfer to the PCB this time.
…
More as the project progresses…
19 Feb
You see, I have a SKUTT 8 kiln for working with PMC (precious metal clay). It’s a nice kiln and all bit it doesn’t have what I would call good temperature control. This got me thinking… rather than spend $300-$800 dollars for a professional kiln controller… I could use the Arduino to make my own. Seems simple enough… I thought. Well, the KILN draws over 15 amps and after a little research, I realized that there was this thing called Proportional-Integral-Derivative feedback control systems… and if I were smart… (I try) that’s what I would be using to control temperature over and undershoot. PMC clay is rather particular about temperatures… and quite expensive… so there is little room for mistakes.
So… initially I need to build a similar controller for my Toner Transfer laminator as a dry run. Lower temperatures and current… so I can test my theory on something that won’t burn down the house.
The first step in that process is to build a breakoutboard… since the MAX6674 is a small surface mount package. Here is the result:

04 Jul
Someone in the Arduino forums mentioned they were having troubles with their Single Sided Arduino board that they built on their own. It reminded me that I wanted to make one for myself. I needed an extra Arduino I could use for RS485 testing and a NON-USB one was preferred.
What a great afternoon project this is. I took the toner transfer PNG file and printed it out so I could use the laminator to do a toner transfer. Once it was etched I could really see the benefit of having a silkscreen on the topside… the trouble is, I’ve never done a board with imagerey on top. I first tried using a heat transfer… just like I did with the copper side but I had no luck. After 10 times through the laminator I still had no luck bonding the toner with the fiberglass side. (I sort of figured that would happen…)
I remembered that I had some 8 1/2 by 11 blank decal sheet on hand and thought maybe I could float the silk screen side decal onto the surface. OK… having never done this before I’m going to now admit I was a bit overconfident, this is really not easy.
Eventually I got it applied. I lost a few bits here and there, but the important parts didn’t tear off. I wanted to coat the decal with FUTURE floor wax but I could not locate the bottle I had for this purpose. It would be a good idea though.
Anyway… here are the results. Powered it up and loaded a sketch… Yippie.

03 Jul
As a part of my ongoing project and seemingly never ending interest in what’s going on outside my window, I purchased a a PARALLAX humidity and temperature sensor. Basically, the Parallax part is a surface mount Sensirion Temperature/Humidity Sensor nicely mounted on a PC board that has 8-PIN DIL pin out for insertion into a solder-less breadboard.
It’s available from MOUSER and from PARALLAX directly.
To get it working, the circuit itself is dead easy. The Parallax part has additional SMD pullups and capacitors right in the 8-pin DIL package so we are only dealing with a few wires. I don’t even need to really show a schematic… the details are in the code.
The code is not really my own creation at all. It is a collection of good ideas from others who have already dealt with this device.
//==========================================================================//
// //
// SHT-11 Humidity & Temperature Version 1.00 December 2008 //
// //
// //
// Written for the Arduino ATmega168 Diecimila and installed & tested //
// on December 12,2008 //
// //
// Multiple Internet references were used, combined and modified //
// for this example, such as Arduino forums and nuelectronics.com //
// //
//==========================================================================//
// Devices Used: //
// Boarduino: USB Powered - Diecimila //
// http://www.ladyada.net/make/boarduino/index.html //
// The Boarduino is a Solderless Breadboard compatible Arduino //
// //
// Parallax Sensirion SHT-11 module //
// http://www.parallax.com (Look for -> "SensirionDocs.pdf" ) //
// //
// The parallax module is a breadboard compatible carrier //
// with the SMD sensor installed by parallax //
// NOTE: Different Pinout than SMD sensor from Sensirion //
//==========================================================================//
// Notes: //
// //
// The Parallax module contains built-in Pullup & Data Pin resistors //
// Sensor Carrier Boarduino //
// Data Pin 1 --> Arduino pin 10 //
// Clock Pin 3 --> Arduino pin 11 //
// Vss Pin 4 --> Arduino GND //
// Vdd Pin 8 --> Arduino 5V //
//==========================================================================//
//==========================================================================//
// Preamble //
//==========================================================================//
#define LED 13
#define T_CMD 0x03 // See Sensirion Data sheet
#define H_CMD 0x05
#define R_STAT 0x07
#define W_STAT 0x06
#define RST_CMD 0x1E
//==========================================================================//
// SHT11 Sensor Coefficients from Sesirion Data Sheet
const float C1
=-4.0; // for 12 Bit
const float C2
= 0.0405; // for 12 Bit
const float C3
=-0.0000028; // for 12 Bit
//const float D1=-40.0; // for 14 Bit @ 5V
//const float D2=0.01; // for 14 Bit DEGC
const float T1
=0.01; // for 14 Bit @ 5V
const float T2
=0.00008; // for 14 Bit @ 5V
//==========================================================================//
// Sensor Variables
int shtClk
= 11; // Clock Pin
int shtData
= 10; // Data Pin
int ioByte
; // data transfer global - DATA
int ackBit
; // data transfer glocal - ACKNOWLEDGE
float retVal
; // Raw return value from SHT-11
float temp_degC
; // working temperature
float temp_degF
; // working tempeature
float r_temp
; // raw working temp
float r_humid
; // Raw working humidity
float dew_point
;
float dew_pointF
;
//==========================================================================//
// coding variables
int dly
;
int timewait
;
byte bitmask
;
//==========================================================================//
// //
// Code Body //
// //
//==========================================================================//
void setup
()
{
pinMode(shtClk
, OUTPUT
);
digitalWrite(shtClk
, HIGH
); // Clock
pinMode(shtData
, OUTPUT
); // Data
pinMode(LED
, OUTPUT
); // LED
Serial.
begin(9600); // open serial Port for 9600 Baud
Serial.println("Resetting Sensor..");
SHT_Connection_Reset
();
// Fast Flash LED to say we are ready
digitalWrite(LED
, HIGH
);
delay
(500);
digitalWrite(LED
, LOW
);
delay
(500);
digitalWrite(LED
, HIGH
);
delay
(500);
digitalWrite(LED
, LOW
);
//-----------------------------
Serial.println("Starting Temperature & Humidity reading every 5 seconds.");
}
//==========================================================================//
void loop
()
//==========================================================================//
{
Serial.println("------------------------------------------------------------------------------");
// SHT-11 Get Temperature
SHT_Measure
(T_CMD
); // retVal = Temperature reading
r_temp
= retVal
;
temp_degC
= SHT_calc_tempC
( retVal
); // Convert to Celcius
Serial.print("Temperature: ");
serialPrintFloat
(temp_degC
);
Serial.print("C");
Serial.print('\t');
temp_degF
= SHT_calc_tempF
( retVal
); // Convert to Fahrenheit
Serial.print("| Temperature: ");;
serialPrintFloat
(temp_degF
);
Serial.print("F");
Serial.print('\t');
Serial.println();
// SHT-11 Get Humidity
SHT_Measure
(H_CMD
); // retVal = humidity reading
r_humid
= retVal
; // Store raw humidity value
Serial.print("Humidity: ");
// Linear conversion
float rh_lin
= C3
* retVal
* retVal
+ C2
* retVal
+ C1
;
// Temperature compensated RH
float rh_true
= (temp_degC
* (T1
+ T2
* retVal
) + rh_lin
);
if(rh_true
>
;100)rh_true
=100; // deal with rh being outside
if(rh_true
<
;0.1)rh_true
=0.1; // a physical possible range
serialPrintFloat
(rh_true
);
Serial.print("%");
Serial.print('\t');
// calculate Dew Point
dew_point
=calc_dewpoint
(rh_true
,temp_degC
); //calculate dew point
dew_pointF
= 9 * dew_point
/5 + 32;
Serial.print("| Dew point: ");
serialPrintFloat
(dew_point
);
Serial.print("C");
Serial.print(" ");
serialPrintFloat
(dew_pointF
);
Serial.print("F");
Serial.println();
// Slow Flash activity LED and create pause between scans
// ...in this case, 5 secs)
timewait
= 0;
while (timewait
<
; 5) {
digitalWrite(LED
, HIGH
);
delay
(500);
digitalWrite(LED
, LOW
);
delay
(500);
timewait
++;
}
}
//--[ Subroutines ]---------------------------------------------------
void SHT_Write_Byte
(void) {
//--------------------------------------------------------------------
pinMode(shtData
, OUTPUT
);
shiftOut
(shtData
, shtClk
, MSBFIRST
, ioByte
);
pinMode(shtData
, INPUT
);
digitalWrite(shtData
, LOW
);
digitalWrite(shtClk
, LOW
);
digitalWrite(shtClk
, HIGH
);
ackBit
= digitalRead(shtData
);
digitalWrite(shtClk
, LOW
);
}
int shiftIn
() {
int cwt
;
cwt
=0;
bitmask
=128;
while (bitmask
>
;= 1) {
digitalWrite(shtClk
, HIGH
);
cwt
= cwt
+ bitmask
* digitalRead(shtData
);
digitalWrite(shtClk
, LOW
);
bitmask
=bitmask
/2;
}
return(cwt
);
}
//--------------------------------------------------------------------
void SHT_Read_Byte
(void) {
//--------------------------------------------------------------------
ioByte
= shiftIn
();
digitalWrite(shtData
, ackBit
);
pinMode(shtData
, OUTPUT
);
digitalWrite(shtClk
, HIGH
);
digitalWrite(shtClk
, LOW
);
pinMode(shtData
, INPUT
);
digitalWrite(shtData
, LOW
);
}
//--------------------------------------------------------------------
void SHT_Start
(void) {
//--------------------------------------------------------------------
// generates a sensirion specific transmission start
// This where Sensirion is not following the I2C standard
// _____ ________
// DATA: |_______|
// ___ ___
// SCK : ___| |___| |______
digitalWrite(shtData
, HIGH
); // Data pin high
pinMode(shtData
, OUTPUT
);
digitalWrite(shtClk
, HIGH
); // clock high
digitalWrite(shtData
, LOW
); // data low
digitalWrite(shtClk
, LOW
); // clock low
digitalWrite(shtClk
, HIGH
); // clock high
digitalWrite(shtData
, HIGH
); // data high
digitalWrite(shtClk
, LOW
); // clock low
}
//--------------------------------------------------------------------
void SHT_Connection_Reset
(void) {
//--------------------------------------------------------------------
// connection reset: DATA-line=1 and at least 9 SCK cycles followed by start
// 16 is greater than 9 so do it twice
// _____________________________________________________ ________
// DATA: |_______|
// _ _ _ _ _ _ _ _ _ ___ ___
// SCK : __| |__| |__| |__| |__| |__| |__| |__| |__| |______| |__| |______
shiftOut
(shtData
, shtClk
, LSBFIRST
, 0xff);
shiftOut
(shtData
, shtClk
, LSBFIRST
, 0xff);
SHT_Start
();
}
//--------------------------------------------------------------------
void SHT_Soft_Reset
(void) {
//--------------------------------------------------------------------
SHT_Connection_Reset
();
ioByte
= RST_CMD
;
ackBit
= 1;
SHT_Write_Byte
();
delay
(15);
}
//--------------------------------------------------------------------
void SHT_Wait
(void) {
//--------------------------------------------------------------------
// Waits for SHT to complete conversion
delay
(5);
dly
= 0;
while (dly
<
; 600) {
if (digitalRead(shtData
) == 0) dly
=2600;
delay
(1);
dly
=dly
+1;
}
}
//--------------------------------------------------------------------
void SHT_Measure
(int SHT_CMD
) {
//--------------------------------------------------------------------
SHT_Soft_Reset
();
SHT_Start
();
ioByte
= SHT_CMD
;
SHT_Write_Byte
(); // Issue Command
SHT_Wait
(); // wait for data ready
ackBit
= 0; // read first byte
SHT_Read_Byte
();
int msby
; // process it as Most Significant Byte (MSB)
msby
= ioByte
;
ackBit
= 1;
SHT_Read_Byte
(); // read second byte
retVal
= msby
; // process result to combine MSB with LSB
retVal
= retVal
* 0x100;
retVal
= retVal
+ ioByte
;
if (retVal
<
;= 0) retVal
= 1;
}
//--------------------------------------------------------------------
int SHT_Get_Status
(void) {
//--------------------------------------------------------------------
SHT_Soft_Reset
();
SHT_Start
();
ioByte
= R_STAT
;
SHT_Write_Byte
();
SHT_Wait
();
ackBit
= 1;
SHT_Read_Byte
();
return(ioByte
);
}
//--------------------------------------------------------------------
int SHT_calc_tempC
( float w_temperature
)
//--------------------------------------------------------------------
{
// calculate temp with float
float temp1
;
// Per the data sheet, these are adjustments to results
temp1
= w_temperature
* 0.01; // divide by 100
temp1
= temp1
- (int)40; // Subtract 40
return (temp1
);
}
//--------------------------------------------------------------------
int SHT_calc_tempF
( int w_temperature
) {
//--------------------------------------------------------------------
// calculate temp with float
int temp1
;
temp1
= w_temperature
* 0.018;
temp1
= temp1
- (int)40;
return (temp1
);
}
//--------------------------------------------------------------------
float calc_dewpoint
(float h
,float t
)
//--------------------------------------------------------------------
// calculates dew point
// input: humidity [%RH], temperature [°C]
// output: dew point [°C]
{ float logEx
,dew_point
;
logEx
=0.66077+7.5*t
/(237.3+t
)+(log10
(h
)-2);
dew_point
= (logEx
- 0.66077)*237.3/(0.66077+7.5-logEx
);
return dew_point
;
}
//--------------------------------------------------------------------
void serialPrintFloat
( float f
){
//--------------------------------------------------------------------
// print results properly with float decimal value
int i
;
Serial.print((int)f
);
Serial.print(".");
i
= (f
- (int)f
) * 100;
Serial.print( abs
(i
) );
}
01 Jul
Here is a simple RS232-485 converter for the PC serial port I developed with the help of a Circuit Cellar article by Jan Axelson about RS485 interfacing.
It uses a 555 as a monostable to enable the transmit mode only when “sending”.
It’s a pretty basic circuit and nothing special is really happening here other than the portion involving the LM555 timer. The termination jumpers allow the 120 OHM termination on the master node as well as the balancing termination resistors connected to +5V and GND.
There were only minor changes throughout development. For example, originally the indicator LED’s were ON unless sending since they were tied to GND. Now then go LIT when sending, which is more intuitive, I suppose.
Here is the circuit:

Here is the board Layout:

PCB Design:

Completed board:

Overall this was an Easy Project.
And yes, this is a HOMEBREW toner transfer method PC board. The DRAWING package is NOT EAGLE but rather ABACOM SPRINT LAYOUT and ABACOM SPLAN.
21 May
While looking at low cost pressure sensors in the Mouser Electronics catalog, I located the FREESCALE MPXAZ6115A as a possible sensor for my project. The sensor has the following statistics; Device: MPX6115, MAX PSI 16.7, MAX kPa 115.
Since barometric pressure here hovers at around 100kPa or so, this sensor would do just fine. The analog output of the sensor is relative to the min/max pressure range of the sensor.
According to my initial tests, the sensor would output about 4.06 volts at 100kPa.
The built-in analog input on the Arduino would also keep the circuit simple and after a few tests I was able to determine the offset value I needed to get correct readings for the localized barometric pressure.
Here is the Arduino Code:
// Nominal Transfer Value:
// Vout = VS x (0.009 x P – 0.095)
// ± (Pressure Error x Temp. Factor x 0.009 x VS)
// VS = 5.1 ± 0.25 Vdc
float Vin;
float P;
void setup()
{
Serial.begin(9600);
}
void loop()
{
Vin = (5.0/1024.0) * analogRead(0);
Vin = Vin + 0.11; // Offset Adjustment
Serial.print(Vin);
Serial.println(" Volts");
P=((Vin/5.0)+0.095)/0.009;
Serial.print(P);
Serial.println(" kPa");
Vin = (P * 0.2952999);
Serial.print(Vin);
Serial.println(" Inches of Mercury");
delay(2000);
}
I’m using a LADYADA Boarduino on a solder-less breadboard for testing. The sensor hookup is dead simple with only one exception that makes it tricky. The part I selected is designed to be surface mounted. I decided to create a carrier board using the board layout software I prefer called SprintLayout from ABACOM in Germany. Other than 5V power and ground connections, the Vout from the carrier board goes directly to the Arduino Analog(0) pin.

To create the PCB board, I use the GOOTIE toner transfer method to apply the layout on the PCB for etching. (google search “gootie PCB” for more info)
Having developed a dislike for the chemical etchant that Radio Shack sells; Ferric Chloride, I have also adopted the etchant that Gootie describes. It is based on the swimming pool chemical Muratic Acid and Hydrogen Peroxide in a 1 to 2 ratio. It’s fast, non-opaque and does not require heating or excessive agitation.
Note: I also recently picked up a used GBC Creative Laminator at the local Goodwill for $14.00. It does an excellent job of applying the toner to the copper on the PCB to be etched. Using an hand iron was OK, but the results were not always predictable.
Here is the Layout:

This is the Component side view or “TOP VIEW” through the board and “yes”, the sensor is actually underneath on the copper side… so the pin out is upside down in this view for that part.
The layout file is here: Pressure.zip
I used 0.100 spaced right angle pins so the board actually sits vertical in the breadboard.
The parts and schematic used are directly from the manufacturers data sheet.
The test program output looks like this:
4.10 Volts
101.65 kPa
30.02 Inches of Mercury
Results: Complete success.
20 May
I have this idea that it would be really nice to keep track of the weather where I live. I know that I can just turn on my TV and watch the Weather Channel but I’m really more inclined to come up with my own technology solution.
I simply want my own personal weather station. I already knew that I didn’t want to dedicate a PC for a weather data collector. If I keep a PC on all the time just to collect data means I’m NOT collecting data if I lose power. If I use a battery powered micro controller, keeping the battery trickle charged from a wall outlet, I would still be collecting data during storms where the potential for power loss is high and when the data being collected is useful.
Being a big fan of micro-controllers, I’m looking into the Parallax BASIC STAMP or the AVR-Based Arduino as a quick way to test out some ideas for weather data sensors.

I learned during my research on the subject that nearly ten years ago Dallas Semiconductor had created a showcase for their 1-wire sensor products in the form of a simple weather station. The Dallas weather station has a Wind Direction Vane, a Wind Speed Anemometer and a temperature sensor.
After a quick trip to EBAY.com, I soon won an auction for a unit of my very own. It turns out that I bid on one of the Original Dallas Semiconductor units. This is somewhat of a complication as this version did not see as many units built as the “version 2″ model built by AAG of Mexico.
All this really means… is that I’m going to have to write a lot of my own code from scratch instead using of what I could find “as-is” published in “NUTS & VOLTS” magazine by the Basic STAMP guru, Jon Williams.
The primary differences between the first model from Dallas and the following AAG model is the fact that the Wind Vane section uses an Analog to Digital converter with a potentiometer instead of magnetic reed switches and silicon serial number chips.
On my unit, when the wind vane moves a magnet inside the unit. This moving magnet closes magnetic reed switch(es) that supply power to 1 or 2 of the 8 Silicon Serial Number devices. The 1-wire master device will search the 1-wire bus and depending on the serial number sent by the device(s) that respond… the position of the wind vane can be determined.

Any solution I come up with needs to constantly search the 1-wire bus and then check the responses against a pre-built table to determine wind direction. It also means that I need to know, in advance, which serial number corresponds to each of the 8 compass directions.
This method does make the version 1 weather station more complicated to setup and monitor. My first tests are going to be done with the Parallax Basic Stamp2P version. The “P” version has more capabilities, including direct support for 1-wire bus devices.
Example Wind Vane response list:
1E00000273822601
3700000273B16F01
540000020057CC01
AE0000020057D401
720000020057D001
FB00000273790101
2000000273AB3401
BD00000273823D01
Notice that each serial number ends in 01. This is the ID section of the number that identifies the device as a Silicon Serial Number device.
Temperature sensors would look like:
5B000000261EB010
So, once we have a temperature sensor ID, we can then send a query to that device ID and ask for a temperature reading.
The real beauty of 1-wire technology is that it really only needs two wires (signal and ground) to create a small “network” of devices that can each be queried uniquely.
Dallas Semiconductor was eventually aquired by Maxim Semiconductor. In 2001, Dallas Semiconductor became a wholly owned subsidiary of Maxim Integrated Products. This also seems to be beginnings of a period where things start to get very quiet on the 1-wire front. Sure, there were still 1-wire products being developed but from the software development standpoint things started to get stale.
Dallas focused alot of attention on JAVA, for example, but the developer tools are now very out of date. They did some C# too but you’d have to locate a really old C# compiler to make use of it. This means that as a PC based 1-wire developer your will need a huge amount of overhead and code bloat just to query a simple 1-wire device for the temperature. When you consider that you can get a micro-controller to do this with a few lines of code… you might come to the same conclusion I did. Let’s chuck the PC and JAVA and do it the simple way.
With the Basic Stamp 2P, the 1-Wire™ devices are supported with two easy-to-use commands:
OWOUT pin, reset, [output data]
OWIN pin, reset, [input data]
The choice for me was simple. I’ll follow up with some examples.