The Detailed Technical Design Engineering Essay

Published: Last Edited:

This essay has been submitted by a student. This is not an example of the work written by our professional essay writers.

Our sensor+transmission unit consists of the following system blocks: 9V battery, voltage regulator circuits, moisture detector, atmega8 microcontroller, 433 MHz TX chip. The 433 MHz TX/RX chips are edge-triggered so they do not accept single-voltage,continous signals. They function best with squre waves up to 100 KHz. We will now endeavour to explain certain system blocks of our sensor+transmitter unit.

Voltage regulator circuits were required to step-down the voltage of the 9 volt battery to 5 volts. The larger capacitor helps "hold up" any falling voltage from the power supply; the smaller capacitor suppresses higher frequency noise and shorter power dips.

Soil moisture sensing unit circuit analysis

This is rather simple circuit yet effective. Here we use the famous 555 timer IC as our core component. The 555 timer here is set in monostable mode in which it acts like a "one shot" pulse generator. Moisture sensing probes are connected between pin2(trigger) and ground and the pin2 is connected to supply(+5V) with a pullup resistor. When the trigger voltage is brought down to a third of supply voltage pin3(output) goes high for a period that is determined by the RC network. The output pulse ends when charge on the capacitor goes up to 2/3 (arond 3.3V)of supply voltage. i.e the period of the output pulse can be changed by altering the RC network T=R3 C3 ln(3) which approximately T=1.1 R3 C3. The sensor probes are stuck to the soil and when suffiecient water covers the probes it becomes closed circuit and trigger goes grounded and output goes high.

We select the RC here as 100K and 10uF so the output stays high for the same time as trigger pulse. We can adjust the sensitivity of the circuit by adding a variable resistor between pin2 and supply voltage,which is one of the user needs for our design since different plants require different moisture levels for a healthy growth.

On average the 555 timer draws 3.4mA supply current when the supply voltage is 5V. This current fluctuates whenever connected to 555 changes state but on average the power input for the 555 timer is 17mW.

Because we use a simple but yet effective circuit, in future if the circuit fails to work we can simply change the timer IC. This will save us time.

Transmitting unit circuit analysis

We have made the communication between sensor and solenoid relay wireless because that is one of our user requirements. First we tried to make the transmission with 433Mhz wireless TX/RX modules with the help of a comparator IC driven to TX module and then we soon realized we live in a RF noisy world that we couldn't even a single pulse without any interference.

So now we are convinced that we cant make any communication without some kind of efficient encoding method including addressing and error checking. We use the AVR micro controller (mc) Atmega8-16PU to do all the encoding and wireless transmission to receiver. Using the Atmega8 also helps for the betterment of the design by following features.

Further modifications can be made to the design without changing much of hardware.

Makes the circuit simple, thus making it less prone to errors.

Makes the repairing of the product easier in future. We can simply change the microcontroller.

Can easily encode the signals with address and checksum. Addressing enables the multiple transmission.

We chose Atmega8-16PU because the cost of this mc is 1.4375$, making the overall cost lesser.

Programming the microcontroller

Since mc is the core component for our transmission part , we spent a lot of time programming the mc in an efficient way. We had no idea about AVR mcs at the beginning and we learnt everything from the scratch.

The 433Mhz TX module receives digital signals and transmits it to receiver. Normally a mc deals with digital signals(5V for1 and 0V for 0) except when dealing with internal peripheral ADC(analog to digital conversion). But luckily our output from sensor is +5V so that we don't have to use the ADC facility in the mc to drive it as an input to one of the pin.

To implement wireless we use the RS232 protocol which is is an asynchronous serial communication protocol widely used in computer communication and digital systems. In simple words this protocol sends a byte, one bit at a time. Like many other microcontrollers AVR also has a dedicated hardware for serial communication. This is called USART-Universal Synchronous Asynchronous Receiver Transmitter. We spent a lot of time in understanding and programming the USART module to implement the wireless transmission.









AVR CPUUSART is connected to CPU by following 6 registers.

Explanation of USART registers

UDR(USART Data Register) . It has two registers one for data storage in receiver buffer the other one for transmitters buffer.

UCSRA(USART Control and Status Register)

There are two more of this same kind UCSRB, UCSRC. All are used to configure USART and store status about USART.

UBRR(USART Baud Rate Register)

This register is used by USART to generate the data transmission at a specified speed (1200/2400/4800bps....). This register is 16bit wide so UBRRH is the high byte and UBRRL is the low byte. UBRR value is calculated according to the following formula

UBRR=(Fosc/16xbaud rate)-1 where Fosc=CPU frequency.

Atmega8 already has an inbuilt 1MHz oscillator. For transmitting complex analog signals we might need to increase the frequency of the oscillator by using crystal oscillators externally. However since we are only transmitting dry/wet signals we wouldn't need to increase the frequency.

To increase reliability of the data transmission we encode the following data bytes in a data packet.

Synchronization byte - This first byte tunes the receiver to accept normal signals.

Address byte - Address of the transmitter. We can imagine this as an authorization code.

Data byte - Dry/wet data.

Checksum byte - (address+data) byte for error checking.

We also invert the input from sensor to the mc so the transmitter sends ones (111111) when the soil is dry.

#include <avr/io.h>

#include <util/delay.h>

#ifndef F_CPU //define cpu clock speed if not defined

#define F_CPU 1000000

#endif //set desired baud rate

#define BAUDRATE 2400 //calculate UBRR value

#define UBRRVALUE ((F_CPU/(BAUDRATE*16UL))-1) //define receive parameters

#define SYNC 0XAA // synchro signal 10101010

#define RADDR 0x44 // address bits 01000100

void USART_Init(void) //Initializing USART


//Set baud rate

UBRRL=(unsigned char)UBRRVALUE; //low byte

UBRRH=(unsigned char)(UBRRVALUE>>8); //high byte

//Set data frame format: asynchronous mode,no parity, 1 stop bit, 8 bit size


//Enable Transmitter and Receiver and Interrupt on receive complete



void USART_SendByte(unsigned char Data)


// Wait if a byte is being transmitted

while(!(UCSRA & (1<<UDRE)));

// Transmit data

UDR = Data;


void Send_Packet(unsigned char addr, unsigned char data)


USART_SendByte(SYNC);//send synchro byte

USART_SendByte(addr);//send receiver address

USART_SendByte(data);//send increment command

USART_SendByte((addr+data));//send checksum


void delayms(unsigned char t)//delay in ms


unsigned char i;




int main(void)


unsigned char a;


DDRB=0xff; //set PORTB for output

DDRC=0x00; //set PORTC for input

PORTB=0xff; //set PORTB default high

PORTC=0x00; //set PORTC default low


{//endless transmission

a=~PINC; //invert the signal from sensor

a=a&0x01; //bit masking for increased reliability in transmission

Send_Packet(RADDR, a);


return 0;


In a real world situation just one sensor for the whole garden/farm is not enough. We need multiple sensors transmitting to a single receiver which actuates the appropriate solenoid valve. Using address in data packets enables us to this feature.

Supply current for mc is 4.3mA when supply voltage is 5V. i.e required power=21.5mW

Supply current for transmitter is 10mA when supply voltage is 5V.i.e required power=50mW

So total power consumption of sensor+transmitter unit=17+21.5+50=88.5mW

Lithium 9V battery (1200mAh) has 38880J energy (1200x10^-3x9x60x60) which powers our sensor and transmitter for approximately 122 hours. In a real life situation 5 days span for a battery is extremely low. We haven't realized this until last minute. Major part of the power goes to transmission and microcontroller. In future during the development we make a few changes to increase battery life. Changes are given below.

Transmit only when soil goes dry. This can be done with the use of interrupts in mc.pin4 and pin5 are the external interrupts for atmega8. These pins are very versatile and we set it to trigger whenever the pin goes from high to low. And we program it in a way to send data to transmitter only when the interrupt is triggered. So the mc stays idle, unless the interrupt is triggered. The idle mc only draws 1mA from 5V supply according to the datasheet. The transmitter will also draw less current when it isn't transmitting anything. This saves us a lot of energy because most of the time the interrupt is going to be high (enough moisture) helping to increase the battery life significantly.

Receiving + relay unit circuit analysis

This unit consist of following system blocks: 9V battery, voltage regulator circuit, 8bit 16x2 LCD module, 433 MHz RX chip, atmega8 microcontroller and relay to the solenoid. We have used the same voltage regulator circuit as before. Now we will endeavour to explain the system blocks in this unit.

Circuit analysis for Receiver+LCD circuit.

The mc is programmed in USART module for serial communication protocol. Rx chip is driven to the RXD interrupt so whenever RX receives any signal interrupt gets triggered. When the interrupt is triggered ISR routine executes every time. The ISR routine function will first check for any errors in the data by using the checksum and if the data is correct it will look for the transmitter address and if this address matches the list of addresses it admits, the mc will output the results.

We also use a LCD module as a visual aid to the user. The Hitachi HD44780 controller is the industry standard for these type of displays. Knowledge of the LCD pins is vital to understand the operation.








Contrast adjust


Register select




Enable signal


Data bit0


Data bit1


Data bit2


Data bit3


Data bit4


Data bit5


Data bit6


Data bit7

LCD modules need to be initialized before displaying any characters. It automatically initializes when power is turned on using the internal reset circuitry. If the power supply conditions for correctly operating of the internal reset circuit are not met, initialization by instruction is required. A set of instructions is used initialize the LCD every time. Then entry mode is set and sequence of characters are sent to display. We can interface the LCD with either 8-bit mode or 4-bit mode. On 4-bit mode we only need to connect the data pins 4-7 to the mc so we save pins for future modifications.

We provide the programming code for "lcd.h" and "rx.c" below. We used the instruction sets given by the data sheet of lcd to initialize and display the characters.

#include <avr/io.h>

#include <avr/interrupt.h>

#include <util/delay.h>


#ifndef F_CPU

//define cpu clock speed if not defined

#define F_CPU 1000000


//set desired baud rate

#define BAUDRATE 2400

//calculate UBRR value

#define UBRRVAL ((F_CPU/(BAUDRATE*16UL))-1)

//define receive parameters

#define SYNC 0XAA// synchro signal

#define TADDR 0x44//the possible addresses of transmitters

#define TADDR2 0x33

void delayms(unsigned char t)//delay in ms


unsigned char i;




void USART_Init(void) //USART initialization


//Set baud rate

UBRRL=(unsigned char)UBRRVAL; //low byte

UBRRH=(unsigned char)(UBRRVAL>>8); //high byte

//Set data frame format: asynchronous mode,no parity, 1 stop bit, 8 bit size


//Enable Transmitter and Receiver and Interrupt on receive complete


//enable global interrupts


unsigned char USART_ReceiveByte(void)


// Wait until a byte has been received

while((UCSRA&(1<<RXC)) == 0);

// Return received data

return UDR;




//define variables

unsigned char taddress, data, chk;//transmitter address

//receive destination address


//receive data


//receive checksum


//compare received checksum with calculated

if(chk==(raddress+data))//if match perform operations


//if transmitter address match

if(raddress==TADDR || raddress==TADDR2)






void Main_Init(void)


DDRC=0xff;//define port C output;

PORTC=0x00;//default PORTC low.


//enable global interrupts



int main(void)






if(PORTC==0x01 ||PORTC==0x02 || PORTC==0x03)







LcdSendInstruction( LCD_DISPLAY_OFF ); //switch off LCD if not watering


//nothing here interrupts are working

return 0;



#include <avr/io.h>

#include <util/delay.h>





#define LCD_RS 0

#define LCD_RW 1

#define LCD_E 2

#define LCD_FUNCTION_SET 0x38 // 0b00110000

#define LCD_FUNCTION_SET_4BIT 0x28 // 0b00101000

#define LCD_DISPLAY_OFF 0x08 // 0b00001000

#define LCD_DISPLAY_ON 0x0F // 0b00001111

#define LCD_DISPLAY_CLEAR 0x01 // 0b00000001

#define LCD_ENTRY_MODE_SET 0x06 // 0b00000110

#define LCD_CURSOR_HOME 0x02 // 0b00000010

#define uint8_t unsigned char // Data type that CV is missing

void LcdSendNibble( uint8_t nibble )



// Output upper nibble on the data ports upper bits

LCD_DATA_PORT = (nibble & 0xF0) | (LCD_DATA_PORT & 0x0F);

// Toggle the E line

LCD_CTRL_PORT |= (1<<LCD_E); // Going up..

LCD_CTRL_PORT &= ~(1<<LCD_E); // ..and down.


void LcdSendByte(uint8_t theByte)


// Send the high nibble


// Shift theByte to get lower nibble in upper part...

theByte = theByte << 4;

// ...and send it



void LcdSendInstruction( uint8_t instruction )


// RS low signals an instruction


// Send the instruction



void LcdSendCharacter(uint8_t character)


// RS high mewans a character to display


// Send the command



void LcdInit(void)


// initialize LCD control lines

LCD_CTRL_PORT &= ~(1<<LCD_RS); // RS low

LCD_CTRL_PORT &= ~(1<<LCD_RW); // R/W low

LCD_CTRL_PORT &= ~(1<<LCD_E); // E low

// initialize LCD control lines to output




// initialize LCD data port to input

LCD_DATA_DDR |= 0xF0; // Data on high four bits of port for now...


LcdSendNibble( LCD_FUNCTION_SET );


LcdSendNibble( LCD_FUNCTION_SET );


LcdSendNibble( LCD_FUNCTION_SET );

// Now, still in 8-bit mode, set the display to 4-bit mode


// We are now in 4-bit mode. Do the rest of the init sequence.

// Need to do a proper function set in 4 bit mode to set number of lines

// and font.

LcdSendInstruction( LCD_FUNCTION_SET_4BIT );

// And finish off with the rest of the sequence

LcdSendInstruction( LCD_DISPLAY_ON );

LcdSendInstruction( LCD_DISPLAY_CLEAR );

LcdSendInstruction( LCD_ENTRY_MODE_SET );

LcdSendInstruction( LCD_DISPLAY_ON );


void Display_message(int n)


int flag=0;


char message1[] = "AUTO WATERING!!";

char message2[] = "Manual watering";

char message3[] = "Auto+manual";

if(n==1 && flag==0) {

while (message1[flag] != 0)







if(n==2 && flag==0) {

while (message2[flag] != 0)







if(n==3 && flag==0) {

while (message3[flag] != 0)








Relay to the solenoid valve circuit schematic

The solenoid valve we are going to use needs 500mA actuating signal and it needs to be connected to a 9V supply, preferably from AC-DC adaptor, because it needs a lot of power to apply pressure to open the valve.

So it's a wise idea to power up the whole circuit with the adaptor instead of a 9V battery which hasn't got enough power.