Gardena & Raspberry Pi
Gardena valve controller
Function:
Create digital interface with toggle input to control Gardena 9V valve
Inputs:
- Open collector
- 3-15V logic level
Implementation:
- PCB
- PIC 12F675 microcontroller
- TL 4426CPA 1A mosfet driver
Software, PCB layout and schematics available below. Build with Microchip IDE for PIC microcontrollers
'C' Code
#include <htc.h>
#include <pic.h>
//__CONFIG(INTIO & WDTDIS & MCLRDIS & BORDIS & UNPROTECT & PWRTEN);
//__CONFIG(FOSC_XT & WDTE_OFF& PWRTE_OFF & BOREN_OFF & CPD_OFF & CP_OFF);
__CONFIG(FOSC_INTRCIO & MCLRE_OFF & WDTE_OFF & PWRTE_ON & BOREN_ON & CPD_OFF & CP_OFF);
//Defines
#define PUSHBUTTON GPIO3 //GP3 - Pushbutton Input
#define FASTFLASHING 0b10000001 //LED's Are Flashing Fast By Default
#define SLOWFLASHING 0b10000101 //This Value Is Xored With FASTFLASHING In The Isr
#define SET 1
#define CLEAR 0
#define TRUE 1
#define FALSE 0
//Global Variable Declarations
//Function Prototypes
void Delay();
unsigned char Debounce();
void Init();
#define ADC (((unsigned int)ADRESH<<8)+ADRESL)
#define DELAY 105
volatile unsigned int adc = 0;
volatile unsigned char tim0 = 0;
volatile unsigned char tim1 = 0;
bit pressed = 0;
void valve ( char i ) {
tim0 = 65; //(ADRESH<10) ? 10 : ADRESH;
if (i) {
GPIO5=1, GPIO1=1, GPIO2=0; //start open valve pulse
while (tim0) ;
GPIO5=0, GPIO1=1, GPIO2=1; //end valve pulse
}
else {
tim0/=6;
GPIO5=1, GPIO1=0, GPIO2=1; //start close valve pulse
while (tim0) ;
GPIO5=0, GPIO1=1, GPIO2=1; //end valve pulse
}
}
//***************************************************************************
//Main() - Main Routine
//***************************************************************************
void main()
{
unsigned char i;
unsigned char s=0;
Init(); //Initialize 12F675 Microcontroller
ei(); //enable interrupts
while(1) //Loop Forever
{
switch (s) {
case 0: if(pressed) s=1, pressed=0; break;
case 1: valve(1); s=2; break;
case 2: for(tim1=DELAY;tim1>0;); s=3; break;
case 3: if(PUSHBUTTON) s=4, pressed=0; break;
case 4: valve(0); s=5; break;
case 5: s=0; break;
default: s=0; break;
}
}
}
//***************************************************************************
//Init - Initialization Routine
//***************************************************************************
void Init()
{
/* Comment out if using simulator, ICD2, or ICE2000 */
#asm //Load Factory Calibration Value Into OSCCAL
call 0x3FF
bsf _STATUS,5
movwf _OSCCAL
#endasm
InitLED(); //Initialize LED variables
ANSEL = 0; //12F675 Only
TRISIO = 0b00001001; //Set All I/O's As Inputs or Outputs
GPIO = CLEAR; //Clear GPIO
VRCON = CLEAR; //Turn Off Voltage Reference Peripheral
CMCON = 0x07; //Turn Off Comparator Peripheral
TMR0 = CLEAR; //Clear Timer0
OPTION_REG = FASTFLASHING; //Set Timer0 Prescaler To Fast Flash LED's
IOCB3 = SET; //GP3 Interrupt On Pin Changed Enabled
GPIE = SET; //Interrupt On Pin Change Enabled
T0IE = SET; //Timer0 Overflow Interrupt Enabled
T0IF = CLEAR; //Clear Timer0 Overflow Interrupt Flag
GPIF = CLEAR; //Clear Interrupt On Pin Change Flag^
PEIE = SET; //enable periferal interups
ADCON0 = 0b00000001; //setup AD & switch ON
ANSEL = 0b01110001; //RC clock and AN0 input
ADIF = CLEAR; //clear AD interrupt flag
ADIE = SET; //enable AD interrupt
T1CON = 0b00000000; //setup Timer1
TMR1H = 0; //clear counter
TMR1L = 0;
TMR1ON = SET; //switch ON
TMR1IF = CLEAR; //clear interrupt flag Timer1
TMR1IE = SET; //enable Timer1 interrupt
GO = SET; //start conversion
return;
}
//***************************************************************************
//Functions
//***************************************************************************
//***************************************************************************
//Isr() - Interrupt Service Routine
// - Timer0 Overflow & GP3 Pin Change Are Used
//***************************************************************************
void interrupt Isr()
{
if ( (T0IE & T0IF) == SET) //If A Timer0 Interrupt, Then
{
// Display(); //Update LED Array
if(tim0) --tim0;
T0IF = CLEAR; //Clear Timer0 Interrupt Flag
}
if ( (GPIE & GPIF) == SET) //If A GP3 Pin-Change Interrupt
{
if (Debounce() == TRUE) { //Debounce Pushbutton
//OPTION_REG ^= SLOWFLASHING; //If Pushbutton Status Is Closed, Then
pressed = 1; //Toggle Timer0 Prescaler (Changes LED Flashing Speed)
}
GPIF = CLEAR; //Clear Interrupt On Pin Change Flag
}
if ( (INTE & INTF) == SET) //If A GP2/INT External Intrrupt
{
INTF = CLEAR;
}
if ( PEIE == SET) //If Peripheral Interrupts Enabled, Check Peripheral
{ //Interrupts
if ( (EEIE & EEIF) == SET) //If A EEPROM Interrupt
{
EEIF = CLEAR;
}
if ( (ADIE & ADIF) == SET) //If A A/D Converter Interrupt
{
adc = ADC;
ADIF = CLEAR;
GO = SET;
}
/* else if ( (CMIE & CMIF) == SET) //If A Comparator Interrupt
{
CMIF = CLEAR;
} */
if ( (TMR1IE & TMR1IF) == SET) //If A Timer1 Interrupt
{
// Display(); //Update LED Array
if(tim1) --tim1;
TMR1IF = CLEAR;
}
}
return;
}
//***************************************************************************
//Debounce() - Debounce Routine
//***************************************************************************
//***************************************************************************
//Debounce() - Debounce Routine
// - returns TRUE if switch is closed
// - returns FALSE if switch is open
//***************************************************************************
unsigned char Debounce()
{
Delay(delaytime); //Delay
if (PUSHBUTTON == OPEN) //If Pushbutton Status Is Open, Then
{
return FALSE;
}
else //Else, Pushbutton Status Is Closed
{
return TRUE;
}
}
//***************************************************************************
//Delay(value) - Delay Routine
// - Delay=value*2.3ms (When OSC=4MHZ)
//***************************************************************************
void Delay(char value)
{
for (outer=value; outer != 0; outer--)
{
for (inner=0xFF; inner != 0; inner--)
{
}
}
return;
}