Garduino: an arduino-sort of- for your garden

garden3

Not really an Arduino this time, but one of the smaller chips (Attiny45) that is used to control the watering of the garden. However, the Arduino was used to develop the software Glimlach.

The schedule is quite simple: The connector at the left is attached to a humidity sensor. Together with R1 that forms a voltage divider that feeds into physical pin 3 of the Attiny which is analog pin 2. The voltage on that pin is then compared to the voltage on physical pin 2 (which is analog pin 3).

If the soil is dry, the resistance between the two poles of the sensor will go up and thus the voltage on pin 3 will drop below the value set with P1. This will make the software in the chip turn Digital I/O 2 (physical pin 7) high. This will signal LED1 and switch on SolidState relais IC2.

In fact, with this the function of the Attiny has not been much different from an Op-Amp comparator such as the 741. The circuit here however has a few extra possibilities  in combination with the software.
Garduino PCB DIY

A problem that surrounds most soil humidity sensors is corrosion. Being in the soil is not such a good environment for metals to begin with, but as a constant current is flowing through the sensor, the subsequent elektrolysis, will speed up the corrosion.
With the Jumperblock (that could be a 3 pins rather than a 4 pin block), the humidity sensor could be fed from pin 5 (Digital 0) and as such only be switched on when a reading is taken. On the print design, there is no actual jumperblock. Using the Vcc or the output of a digital pin to feed the humidity sensor is a matter of cutting a copper track at one place and adding a wire somewhere else.
garduinoprint-3

Download PCB

With a microprocessor it is also very easy to let a pump flow for a set amount of time which with an opamp circuit wld require another IC such as a 555 or at least an RC network.
One could also use pin 1 (analog 1, digital 5) to attach say an LDR to ensure that all irrigation is only to take place at night or in the morning.
Also, there is a level switch attached to pin 6 (Digital 1). This switch is mounted in the water reservoir  in which the punp (M1)  is situated. When the water level goes too low -endangering the pump to run dry- the microprocessor will not switch on the pump anymore. Currently there is no optical indication for this, other than looking into the reservoir, but an LED with a 330 R resistor could be mounted parallel to R5 and thus give an optical indication of the low waterlevel. The float switch I am using is no more than a reed contact at the outside of the container and a magnet attached on a floating device. You could also use a mercury tilt switch, or a micro switch that is handled by a floating lever.

Diode D1 is a 5V1 Zenerdiode and protects the port against surges that might be carried over long lines to the humidity sensor.
The choice for the SolidState Relay was a practical one. It was rather cheap and I could not find a small relay that could switch 230 Volts with just a 5 volts input. I know they exist coz I used them before, just could not quickly find them this time and I had the 39FM22. There is always a question wether an SSR is a good choice to switch an inductive load, but it works for me

The Sensor

DIY humidity sensor
A lot has been written on how to construct a humidity sensor, but what has always worked for me is just two pieces of galvanized iron. These could be nails, but dont rule out old clothes hangers that are often from galvanized material as well.
Forget about the constructions with Gypsum: tedious, slow acting and within a few months in the soil these will fall apart.
Soldering to galvanized iron may be a bit difficult, but what works is to just file off a bit of the surface, wrap a wire around that and solder that. Then cover it with heatshrink tubing.

Though you could just stick the two pieces of  galvanized iron in the soil, I prefer to attach them to eachother so they have a somewhat fixed distance from eachother. A piece of plastic electra pipe is well suited for this.

With regard to R1, the resistor that forms the lower half of the voltage divider with the humidity sensor, 10 k works for me, but it is best to measure the resistance of the humidity sensor when it is inserted in your soil that has the proper humidity. It is best to choose a resistor that is more or less equal to the resistance of your humidity sensor in that soil. Setting P1 halfway then should already bring you fairly close to the proper switch point.

In principle it is possible to use stainless steel as well, but that is just very hard to solder on, but a clamp connection might work just fine.
It is unwise to use copper for the humidity sensor. Put two copper wires in the soil and you most likely will measure a relatively substantial voltage over these. With that the reading on your arduino could become instable and could be dependent on polarity as well. Galvanized iron has this problem to much lesser extend.

The Software
------
/* Garden 3
april 2012
Sensors:
-Humidity spike on analog pin2

*
*----------------------Humid------------------------------
* Schematic:
*[Ground] -- [10k-pad-resistor] -- | -- [Spikes] --[Vcc]
*

*                                Analog Pin 2
*
*
ATTiny pins
Physical  Analoog  Digital
1           0          5   Reset, PinChange Interrupt
2           3          3   INT0,3
3           2          4   INT0,4
4           Ground
5                      0   INT0,0
6                      1   INT0,1
7           1          2   INT0,2
8           Vcc
*/
//Pin definities
int levelPin= 3; //analogue Pin3  ->Physical pin2  set level int humidPin=2;  //analogue Pin2  ->Physical pin3  Humidity sensor
int pumpPin =2;  //digital  Pin2  ->Physical pin7  Pump int emptyPin=1;  //digital  Pin1  ->Physical Pin6  waterlevel
int spikePin=0;  //Digital  Pin0  ->Physical Pin5  Extra for intermittent switching of spike
// Variable setting
int moist=0;    //float is not necessary
int irrigate=0;   //level for irrigation
int level=0;
//The following function, "setup", must always be present
void setup()
{
pinMode(levelPin,INPUT);// set level
pinMode(humidPin,INPUT);// measures humidity
pinMode(emptyPin,INPUT);//measures reservoir
pinMode(spikePin,OUTPUT); //for alternative supply to spikes
pinMode(pumpPin,OUTPUT);//  Output for Relay
digitalWrite(pumpPin, LOW);
digitalWrite(spikePin, LOW);
//uncomment for Attiny13
//analogReference(0);
}

void loop() //This function must always be present
{
level=  digitalRead(emptyPin);
/*
First read the level set with P1 on the levelPin and store that in 'irrigate'
*/
irrigate=sample(levelPin); /*

Then we read the Humidity sensor.
We'll first have to set the spikePin to HIGH, in case that is used to feed the sensor. 
After the reading we set it back) If the value read ('moist') is smaller than what is 
considered dry ('irrigate') then the pump should be switched on for a specific time. 
This is done by indicating a higher treshhold for switching the pump off
*/
digitalWrite(spikePin, HIGH);
moist=sample(humidPin);  //read humiditySensor
digitalWrite(spikePin, LOW);
level=  digitalRead(emptyPin);
if (moist <= irrigate) digitalWrite(pumpPin, level); if (moist >= irrigate+5) digitalWrite(pumpPin, LOW); // prevents  Jitter
//end loop 
}
int sample(int z)
/* This function will read the Pin 'z' 5 times and take an average. 
Afterwards it will be mapped by dividing by 4
*/
{
int i;
int sval = 0;
for (i = 0; i < 5; i++)
{     sval = sval + analogRead(z);// sensor on analog pin 'z'
}
sval = sval / 5;    // average
sval = sval / 4;    // scale to 8 bits (0 - 255)
return sval;
}
Getting the code in the Attiny

Plenty of tutorials have been written about that, but you could have a look here.

Soil

What soil you use is up to you but you may want to consider ‘Mel’s Mix’: 1/3 of vermiculite, 1/3 of peat, 1/3 of compost

Other Uses for plants

Due to the seasonal change, this device would sit idle in the winter when I am not really growing anything and leaving a pump outside in a bucket of water is a foolish thing. However, it has a different use then. I bring it inside, replace the humidity sensor with a thermistor and use it to switch on a 25 watt lamp that I use as a heating element in my propagator.

When the temperature drops the resistance of the thermistor goes up and therefore the voltage on pin 3 drops. When that drops below the point that is set with P1, the SSR closes and the lamp switches on.

Useful links

 

Advertisement

Arduino on 1.5 Volt

arduino_1-5V

Compilation of 3 previous articles with an Atmega328 running on 1.5 Volt and an adapted Led circuit around D13. Instead of an AA battery you could also use a 1.2V NiCad cell and add a solarcharger to that.

The HT7750A supposedly can deliver 200mA. The HT7750 only 100. (although the datasheets make me doubt that). All in all this DC-DC converter may be a better option

Note: There is a mistake in the circuit: the 4.3 Mhz Crystal should be a 16 Mhz

Solving the D13 problem on your Arduino

De Arduino series traditionally has an LED on digital Pin13, and the Blink program is usually the first program people use on their Arduino, kust to see if it works.
The disavantage of the LED that is coupled via a 1 k resistor is that it can disturb the function of the Pin as an input. There are basically 3 options to solve this program if you are building your own Arduino:

  • Leave out the LED all together
  • Connect it via a jumper
  • Connect it via a FET

Ofcourse leaving it out will mean some loss of compatibility with the Arduino
Connecting it via a jumper may require some fiddling, especialy when the board is already built into a casing, also you may lose the jumper. Using a FET however is care free. The gate of a FET has a high impedance so it wil not load the pin when used as an input.

d13

Simple Arduino revisited

The earlier presented Simple Arduino is a good design, but it is not so efficient in using space. There is a lot of ‘whitespace’ on the stripboard. With a little bit of effort a lot of space can be saved:
Choose a smaller pushbutton. Leave out the LED on D13, you know if your circuit is working or not. The illustration below is as seen from the component side
render-e

I have built the circuit on a board of the same size and it clearly shows how much room is left for hardware of your own choice. You will not find a powerLED on the circuit, but that is easy enough to add. You could also make the circuit even more compact by shifting the 7805, C4, C5 and D1 to the space left of the  ATMEGA (and cutting tracks q,r and s ofcourse).

Atmega644

The regular Arduino has plenty of pins for most projects, but if you need a bit more, then the next step is the Atmega, with lots of pins and an SMD chip. For DIY the Atmega644 is a solution. A bit more power than the 328, but still available in DIL. It is the same chip as used in the ‘Sanguino’. 

atm644e
PA0-7 are the analog ports.
PB0-7 are Digital ports 0-7
PD0-7 are Digital ports 8-15
PC0-7 are Digital ports 16-23

R3 and LED2 are the standard ‘test Led’  circuit. For compatability it should be connected to pin 19 (PD5=D13). Do this via a jumper, so the test LED can always be switched off in case you need to put something else on that pin.

Arduino comparison

Characteristic Sanguino Arduino Arduino Mega Leonardo
Processor atmega644P atmega328 atmega1280 atmega32U4
GPIO Pins 32 20 54 26
Analog Pins 8 6 16 12
PWM Pins 6 6 14 8
Flash Memory 64K 32K 128K 32K
RAM 4096 bytes 2048 bytes 8192 bytes 3072 bytes
EEPROM 2048 bytes 1024 bytes 4096 bytes 1024 bytes
External Interrupts 3 2 32 13
JTAG yes no yes yes
I2C yes yes yes yes
SPI yes yes yes 2
USARTs 2 1 4 1
Onboard USB<->Serial Converter? no yes yes in-chip
         
         

Driving a stepper with bitwise manipulation of the PORT

In a previous article I described driving a steppermotor with an arduino. I like to use that as an example for writing directly to the ATMega328’s registers to drive the stepper.
Normally you would first set the chosen Digital pins on the Arduino to Output with pinMode and then you would set the Value of the pins with DigitalWrite. If you are using four pins to drive your stepper, this would require 4 DigitalWrite cycli per step.

“digitalWrite” is not the most efficient or fastest way to write to a port as it takes many cycli. Also, the pins are written to sequentially instead of at the same time.
That is not really a big problem for steppers as those are not time critical. It is possible however to write to all 4 pins at the same time.

If you use digital pins 8-11 to drive the motor, you are using the port ‘B’ (pins 8-13). That port can be manipulated by 3 registers and the arduino website describes those.  We need to set two registers, the DDRB and the PORTB register.

The DDRB register determines which pins will become output and if we use pins 8-11, the statement:
DDRB=B00001111; 
would set pins 8-11 to output.

There is a problem however because we also write to the higher pins –12 and 13-  and actualy to some more places that might already have a certain value that we are now altyering. It is therefore better to state:
DDRB= DDRB | B00001111;
 
This ‘logical OR’ function, does not change the upper four bits that might have been set to 1, it just sets the four lower bits to HIGH.
This basically takes care of the 4 pinMode statements.

The four ‘digitalWrite’ statements are taken care of by the PORTB register, but then we run into a bit of a problem: if for our first step we need only the first and the fourth bit to be HIGH and the 2nd and 3rd bit to be LOW, we cannot just write:
PORTB=B00001001;
Yes, it will set the required pins high and low, but like with the DDRB register, we may have previously set the upper 4 bits of the register and those are now set to ‘0’ again.

We can also not use the: 
PORTB=PORTB | B00001001; because  this will leave any pins in the lower 4 bits (D8-D11)  that were previously set to HIGH untouched and they remain HIGH.

So we need a function that leaves the upper 4 bits untouched, but sets the lower 4 pins to the exact value we want.
That is done with a mask:
mask=B00001111;

This mask has the pins that we want to change set to HIGH and the pins that need to remain as they are set to LOW. That allows us to write to the exact pins we want in the register with the following statement:
PORTB = (PORTB &~mask) | (B00001001); 
(actually:   PORTB = (PORTB &~mask) | (B00001001 & mask);//gives the same result )
so, the entire program will look like this:

// uses two coils and thus has extra torque
//pins D8-11 are used for the motor control

int delayTime = 100;
int mask=B00001111;// sets only the last four bits
void setup() {
 DDRB = DDRB | B00001111; //set D8-D11 to output                        
}
void loop() {
 PORTB = (PORTB &~mask) | (B00001001); 
 delay(delayTime);
 PORTB = (PORTB &~mask) |  (B00000101);
 delay(delayTime);
 PORTB = (PORTB &~mask) | (B00000110);
 delay(delayTime);
 PORTB =  (PORTB &~mask) | (B00001010);
 delay(delayTime);
}

Identifying and using a stepper motor on Arduino

If you buy a new steppermotor for a project there is usually some documentation telling you how to connect it.
However, we do not always buy steppermotors with documentation: sometimes you have an old one, sometimes you pull it out of an old unused device or get it from a surplus store.
P1040286

I found a steppermotor that I had probably bought 30-35 years ago and never used (over ambitious). It did not offer much info other than: 55SI-25D AWC 7.5 DEG 36 Ohm and that it was from Oct 83 and came from Japan. It had six wires, but other than some handwritten labels mentioning colors and numbers (that were even corrected), it offered no clue on what connection was what. Initially, also the internet offered no help other than some questions about that type of motor (Although I recently found some info [now gone]).

So, how to identify what was what? Well first the number of  connections –6-   (brown, yellow, blue, red, white and white) suggested it was a unipolar steppermotor and I suspected the two white ones to be the common connection. To establish how the rest of the wires where connected it was time for the multimeter and I set up a small table in which I could enter the resistance values I measured:

white 1 white 2 red blue yellow brown
white 1 x 36Ω 36Ω
white 2 x 36Ω 36Ω
red 36Ω x 72Ω
blue 36Ω x 72Ω
yellow 36Ω 72Ω x
brown 36Ω 72Ω x

For those having trouble reading the symbols: ∞ means that there was an infinite resistance (i.e. not connected) and x means that there is no need to measure it as it is the same wire.

If you don’t have a multimeter, it becomes a bit harder but then you can also find which coils belong together: if you short a coil the resistance in manually turning the axis increases

unipolarcoilsObviously this was a motor with 4 coils, that each have a white common connector and the table tells us that red and brown are the coils connected to ‘white 1’ and that yellow and blue are the pair with ‘white 2’ as a common connector.

However, with a unipolar stepper the coils need to be driven in a certain sequence, otherwise the motor won’t turn at all, or will have only little power and though from the table we now know what coils belong to a pair, we still do not know what the sequence of the coils is.

In other words take for instance the red and the brown pair. Is red coil 1 and brown coil 2 or is it the other way around?  Well, that is a bit tricky because even the numbering of the coils is not always standard.

There is a way of measuring which coil is which, by applying voltage to one coil and then adding voltage to another coil, while feeling if the shaft turns at all and what way. But that is actually just as much work as connecting it to an arduino and switching a few pairs of wires to test. Once you have established –as we did in the table above-  what pairs are connected. It is really not that much work anymore.

coilsSo for now let’s forget about coil numbers and look a bit more at the functions and how to drive the coils.
So, for the time being we will just call them coil 1a,1b, 2a and 2b. we don’t know which one is a and b but we do know that it is the red-brown pair vs the blue yellow pair.

As none of the coils belonging to the same pair should be energized at the same time, the sequence must be either:
red yellow brown blue
or
red blue brown yellow.
As it turns out, it is red-yellow-brown blue to turn the motor clockwise and yellow-red-blue-brown to turn the motor counter clockwise

There are in fact 4 ways of  driving a steppermotor:

  • Wave driving (sometimes also called (“one-phase on, full step” ) is the simplest as only one coil is on at any one time. This uses least current but also produces the least amount of torque. The coil activation sequence would be: 1a-2a-2b-1b-1a etc
  • Half stepping is done by alternating between activating a single coil and two coils at the same time. Due to the smaller step angle, this mode provides twice the resolution and smoother operation. Half stepping produces roughly 15% less torque than dual phase full stepping. Modified half stepping eliminates this torque decrease by increasing the current applied to the motor when a single phase is energized. The torque fluctuates between utilising a single coil and both coils. the coil activation sequence would be:
    1a-1a2a-2a-2a1b-1b-1b2b-2b-2b1a,
  • Full stepping (sometimes also called  “two-phase on, full step”) is when two coils are always energised at the same time. This gives the motor maximum torque but will require more current more current. This looks like: 1a2a-2a1b-1b2b-2b1a.
  • Microstepping is a technique that increases motor resolution by controlling both the direction and amplitude of current flow in each winding. Current is proportioned in the windings according to sine and cosine functions. Microstepping is at the expense of drastic loss in torque. On the Arduino microstepping can be achieved  with PWM. However, unless you really need it, I wouldnt bother

To drive the motor continuously, we just apply power to the two windings in sequence. Assuming positive logic, where a 1 means turning on the current through a coil, the following two control sequences will each spin the motor clockwise 24 steps:

  Winding 1a 1000100010001000100010001
  Winding 1b 0010001000100010001000100
  Winding 2a 0100010001000100010001000
  Winding 2b 0001000100010001000100010
              time --->

  Winding 1a 1100110011001100110011001
  Winding 1b 0011001100110011001100110
  Winding 2a 0110011001100110011001100
  Winding 2b 1001100110011001100110011
              time --->

Note that the two halves of each winding are never energized at the same time. Both sequences shown above will rotate a permanent magnet one step at a time. The top sequence only powers one winding at a time, as illustrated in the figure above; thus, it uses less power. The bottom sequence involves powering two windings at a time and generally produces a torque about 1.4 times greater than the top sequence while using twice as much power.

Anyway, a simple program to test the motor would be:

int motorPin1 = 8;
int motorPin2 = 11;
int motorPin3 = 10;
int motorPin4 = 9;
int delayTime = 500;

void setup() {
  pinMode(motorPin1, OUTPUT);
  pinMode(motorPin2, OUTPUT);
  pinMode(motorPin3, OUTPUT);
  pinMode(motorPin4, OUTPUT);
}

void loop() {
  digitalWrite(motorPin4, LOW);
  digitalWrite(motorPin2, LOW);
  digitalWrite(motorPin3, LOW);
  digitalWrite(motorPin1, HIGH);
  delay(delayTime);
  digitalWrite(motorPin1, LOW);
  digitalWrite(motorPin2, LOW);
  digitalWrite(motorPin3, LOW);
  digitalWrite(motorPin3, HIGH);
  delay(delayTime);
  digitalWrite(motorPin1, LOW);
  digitalWrite(motorPin4, LOW);
  digitalWrite(motorPin3, LOW);
  digitalWrite(motorPin2, HIGH);
  delay(delayTime);
  digitalWrite(motorPin1, LOW);
  digitalWrite(motorPin2, LOW);
  digitalWrite(motorPin3, LOW);
  digitalWrite(motorPin4, HIGH);
  delay(delayTime);
}

Now you cannot of course run the motor directly from the arduino ports. You can do this with special Motordrive IC’s like the L298D or with discrete components such as power transistors or FET’s, but a fairly cheap and simple IC that can be used is the ULN2003 darlington driver (or the MC1413).

A note though: with 6 wire unipolar steppermotors you can decide to forget about the  middle connectors (the ‘whites’ in this case) and drive them like a bipolar. That is something you cannot do  with a ULN2003, you need an H- bridge for that

If you do not know the voltage of a motor, then just start with 5 Volts and go up. Many steppers are actually 12 V. The ULN2003 can take 50 Volts and deliver 500mA per gate. As the motor I use has a coil resistance of 36 Ohm and the Voltage is 12Volt, that will be 333mA so that should be OK. Nevertheless, if you plan on using the motor at high speed, some cooling of the ULN2003 might be a good idea. There are DIL heat sinks available but you could also epoxy a piece of copper or aluminium U-tube on it. The ULN2003 is not the most efficient chip and the Darlington has a high voltage drop. The chip therefore dissipates a lot of energy.

Wire it up as follows:

uln2003-test

The connections of the header are chosen as above since that was the sequence of the header on the motor (but remember red-brown are a pair and yellow red are a pair).

On using the test program above, the following connections would make the motor step properly:

D8-> red
D11->brown
D10->yellow
D9->blue

This seems as one would expect coz it is the 1a,2a,1b,2b or at least the 1x2x1y2y sequence. Similarly, one would expect that

D8 –>red
D11->blue
D10->yellow
D9->brown

(basically switching ‘1’ and ‘2’)  would make the motor step backwards and it does.

When the motor is used with the ‘Stepper.h’ library from the Arduino (e.g. in the Tom Igoe “Stepper_oneStepAtATime”), we see the same results.

For those interested to try the stronger torque program and try some direct bit manipulation at the same time have a look here:

As the steppermotor takes up 4 of the 7 outputs, you may want to consider using the other 3 to drive relais or a couple of small dc motors. The outputs of the ULN2003 may be parallelled for higher output current. The 3 darlington’s left therefore could drive a 1.5 Amp load.

If you need to drive two steppermotors consider the 2803 as that contains 8 darlington drivers rather than 7.

However, there is something else you can do with the spare gates, Remember the stepping sequence t o drive the motor?

Steps Coil 1 Coil 2 Coil 3 Coil 4
1 1 0 1 0
2 1 0 0 1
3 0 1 0 1
4 0 1 1 0
1 1 0 1 0

There is a pattern in this table: Coil 1 is always the opposite of Coil 2 and the same goes for Coil 3 and 4. It is therefore possible to cut down on the number of pins from the Arduino (or other microcontroller) to just two, by using additional NOT gates.

The ULN2003 can provide these:

uln2003-2lines

Programming then is very easy by toggling the two pins high and low.

If doing work with the Arduino and a stepper motor, consider AccelStepper as a library. It is more flexible.
MOTEUR55SI
Good site here (Spanish) and translated

Driving an Attiny? or here.
here
Steppermotor wiring.

Protection for Arduino ports

If you are using long wires to transport a signal to e.g. the analog entrances of your arduino, then voltages sometimes can be generated in those wires that are a bit too much for your Arduino and you may blow it up.

protection_circuitA small protection circuit may prevent a lot of problems and aggravation. Of course the Zener and resistor should be placed close to the chip.

Should you be considering building the simple Arduino board, described earlier, then take advantage of the space that is still present on the strip board, right in front of the Analog gates. Cutting the strip, bridging that cut with a resistor and connecting the zener between anolog and ground would be easy to do.