Touch Capacitivo per Tapparelle

Quando il classico interruttore bistabile up/down non basta o meglio non si sposa bene con l’arredamento della vostra casa, quello che occorre è un po’ di tecnologia con un pizzico di eleganza, ovviamente touch!

Tutto è nato dal problema di dover movimentare una tapparella elettrica senza dover per forza usare un antiestetico interruttore bistabile up/down tipo questo:

 

Per questa applicazione ho scelto di utilizzare un PIC12F1840, un microcontrollore Microchip ad 8pin per poter pilotare due relè: uno usato come deviatore per alimentare alternativamente le due fasi del motore elettrico e permettere la rotazione oraria/antioraria, l’altro usato come interruttore generale per staccare totalmente l’alimentazione.

Come “sensori” capacitivi per realizzare l’interfaccia touch ho utilizzato due lamine di rame da 1mm di spessore, dimensioni 5x5cm ognuna delle quali collegate direttamente ad un pin analogico del microcontrollore.

Ricapitolando, usando un microcontrollore ad 8pin, togliendo i due pin di alimentazione ed il pin MCLR che è utilizzabile solamente come ingresso digitale,  restano solamente altri 5 pin I/O.

Di questi 5 pin, visto che due sono utilizzati come uscite digitali per pilotare i due relè ed altri due pin sono ingressi analogici per i due “sensori” capacitivi, resta solamente un unico pin per poter pilotare i due led di indicazione up/down!

Per poter comandare due led con un singolo pin ho sfruttato la caratteristica “three-state” di questi pin. Ogni pin I/O può infatti essere impostato in tre modi diversi:

  • uscita digitale a livello logico basso (0V)
  • uscita digitale a livello logico alto (5V)
  • ingresso digitale ad alta impedenza

In questo modo, collegando opportunamente i due led si possono accendere alternativamente oppure spegnerli entrambi con l’utilizzo di un unico pin del microcontrollore. Per ulteriori informazioni vedi charlieplexing 😉

Ecco lo schema elettrico: 

 

Questa è una foto durante le fasi di test:

 

 

Questo invece è il lavoro finito su basetta millefori e lastra di plexiglass da 5mm per i due “sensori”:

 

 

Ecco un video che mostra il funzionamento:

 


 

L’installazione è stata eseguita incassando il modulo all’interno di una normale scatoletta “portafrutti” a sua volta incassata a muro tipo questa:

 

 

Successivamente è stato incollata una lastra di vetro satinato da 5mm per nascondere il tutto. Questo è il risultato finale:

 


 

 

Qui di seguito fornisco il sorgente di questo progetto, ovviamente per una corretta compilazione sono necessarie le librerie mTouch di Microchip che potete scaricare gratuitamente da questo link.

/************************************************************************************************\

    TouchTapparelle v1.0 - PIC12F1840
    www.ajk.altervista.com

    Copyright (c) 2012, Alberto Garbui aka AjK
    All rights reserved.

    Redistribution and use in source and binary forms, with or without modification, 
    are permitted provided that the following conditions are met:

    -Redistributions of source code must retain the above copyright notice, this list 
     of conditions and the following disclaimer.
    -Redistributions in binary form must reproduce the above copyright notice, this list 
     of conditions and the following disclaimer in the documentation and/or other 
     materials provided with the distribution.
    -Neither the name of the AjK Elettronica Digitale nor the names of its contributors may be 
     used to endorse or promote products derived from this software without specific prior 
     written permission.

    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 
    EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 
    OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 
    SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 
    INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
    PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
    INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
    LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

\************************************************************************************************/
 #include "mTouch.h"                            // Required Include

//definizione connessioni

//LEDS UP/DOWN (singolo pin)
#define LED_UP();		TRISA5=0;LATA5=0;
#define LED_DOWN();		TRISA5=0;LATA5=1;
#define LED_TOGGLE();	TRISA5=0;LATA5=!LATA5;
#define LEDS_OFF();		LATA5=0;RA5=0;TRISA5=1;

//RELE' UP/DOWN
#define SWITCH_UP();	LATA0=1;
#define	SWITCH_DOWN();	LATA0=0;

//RELE' MOTORE ON/OFF
#define	MOTOR_ON();		LATA1=1;
#define MOTOR_OFF();	LATA1=0;

#define TOUCHDELAY		1000	//tempo permanenza touch per attivare il motore (ms)
#define	TIMEOUTMOTORE	17500	//tempo attivazione motore per una corsa intera (ms)

//definizioni non modificabili
#define TOUCH_UP 0
#define TOUCH_DOWN 1
#define OFF	2
#define SWITCHDELAY	500	//intervallo tra switch ed attivazione motore (ms) (necessario!)
#define MAXDELAY	65000 //48ms * 65535 =circa 52minuti
#define INTERRUPTPERIOD	50	//ms di periodo interrupt

// CONFIGURATION SETTINGS
__CONFIG(FOSC_INTOSC & WDTE_OFF & PWRTE_OFF & MCLRE_OFF & CP_OFF & CPD_OFF & BOREN_OFF & CLKOUTEN_OFF & IESO_OFF & FCMEN_OFF);
__CONFIG(WRT_OFF & PLLEN_ON & STVREN_OFF & BORV_25 & LVP_OFF);

//variabili globali
unsigned int tempoDelay;
unsigned char statoTapparella;
unsigned char timerMotore=0;		//flag avvio conteggio motore
unsigned int tempoMotore=0;			//conteggio tempo motore

// PROTOTIPI
void System_Init(void);
void interrupt ISR(void);
void setLed(unsigned char touch);
void setSwitch(unsigned char touch);
void waitMTOUCH_RELEASED(unsigned char touch);
void setupTimer1(void);
void delay_ms(unsigned int ms);
void checkTouch(unsigned char touch);
unsigned char checkPresenza(unsigned char touch, unsigned int ms);

void main(void)
{

	System_Init();          //init porte/oscillatore/interrupt
    mTouch_Init();          //init mTouch
    setupTimer1();			//avvio conteggio tempo con timer1 ed interrupts

	setLed(TOUCH_UP);		//accendo led up
	unsigned int i,j;
	for(i=500;i>50;i-=50)	//animazione iniziale
	{
		for(j=0;j<3;j++)
		{LED_TOGGLE();		
		delay_ms(i);}
	}
	for(i=0;i<20;i++)
	{
		LED_TOGGLE();		
		delay_ms(100);
	}
	LEDS_OFF();				//spengo i led
	delay_ms(1000);

    while(1)				//ciclo infinito principale
    {  
		if(mTouch_isDataReady())   		
        {
			mTouch_Service();       
			checkTouch(TOUCH_UP);		//controllo entrambi i sensori 
			checkTouch(TOUCH_DOWN);		//UP/DOWN
		}
    }//end while(1) 
}//end main()

void checkTouch(unsigned char touch)
{
	if((mTouch_GetButtonState(touch) == MTOUCH_PRESSED))
	{ 
		setLed(touch);		//se rilevo la prensenza del touch, attivo il led corrispondente

		if(checkPresenza(touch,TOUCHDELAY))					//se rilevo una pressione prolungata
		{
			MOTOR_OFF();									//mi assicuro che il motore sia spento
			delay_ms(SWITCHDELAY);							//delay per scaricare tensioni residue
			setSwitch(touch);								//imposto lo switch UP/DOWN
			delay_ms(200);
			MOTOR_ON();										//attivo il motore
			tempoMotore=0;									//azzero il tempo motore
			timerMotore=1;									//avvio il conteggio del tempo

			waitMTOUCH_RELEASED(touch);						//aspetto il rilascio

			//ora aspetto la fine del timeoutMotore oppure una pressione per lo stop
			while(1)
			{
				if(tempoMotore>(TIMEOUTMOTORE/INTERRUPTPERIOD))	//se supero il timeout
				{	
					MOTOR_OFF();								//spengo il motore
					timerMotore=0;								//fermo il conteggio del tempo
					break;										//esco
				}
				if(mTouch_isDataReady())  
        		{
					mTouch_Service();  						//se rilevo un touch qualsiasi esco     
					if((mTouch_GetButtonState(TOUCH_UP) == MTOUCH_PRESSED))
					{
						//setLed(TOUCH_UP);					//accendo il led UP		
						MOTOR_OFF();						//spengo il motore
						waitMTOUCH_RELEASED(TOUCH_UP);		//aspetto il rilascio
						break;
					}
					if((mTouch_GetButtonState(TOUCH_DOWN) == MTOUCH_PRESSED))
					{
						//setLed(TOUCH_DOWN);					//accendo il led DOWN		
						MOTOR_OFF();						//spengo il motore
						waitMTOUCH_RELEASED(TOUCH_DOWN);	//aspetto il rilascio
						break;
					}
				}
			}
			delay_ms(SWITCHDELAY);							//delay per scaricare tensioni residue
			setSwitch(TOUCH_DOWN);							//imposto lo switch DOWN (relè a riposo)
			LEDS_OFF();										//spengo i led dopo un'eventuale animazione
		}else{
			LEDS_OFF();
		}
		delay_ms(1000);										//aspetto 1sec					
	}else{ 
		LEDS_OFF();				//se non rilevo la presenza spengo i led
	}
}

void waitMTOUCH_RELEASED(unsigned char touch)
{
	//per sicurezza inserisco un timeout di 30sec
	unsigned int const timeout=30000/INTERRUPTPERIOD;	 
	tempoDelay=0;									//inizio il conteggio del tempo per il timeout
	while(1)										//aspetto il rilascio
	{
		if(tempoDelay>timeout)break;				//esco con timeout
		if(mTouch_isDataReady())  
    	{
			mTouch_Service();       
			if((mTouch_GetButtonState(touch) != MTOUCH_PRESSED))break;
		}
	}
	delay_ms(500);									//delay antirimbalzo dopo il rilascio
}

void setLed(unsigned char touch)
{
	switch(touch)
	{
		case TOUCH_UP:
			LED_UP();
			break;
		case TOUCH_DOWN:
			LED_DOWN();
			break;
		default:
			LEDS_OFF();
			break;
	}
}

void setSwitch(unsigned char touch)
{
	if(touch==TOUCH_UP)
	{
		SWITCH_UP();
	}else{
		SWITCH_DOWN();
	}
}

unsigned char checkPresenza(unsigned char touch, unsigned int ms)
{
	unsigned int timeout=ms/INTERRUPTPERIOD;
	if(timeout>MAXDELAY)timeout=MAXDELAY;
	tempoDelay=0;
	while(tempoDelay<timeout)
	{
		if(mTouch_isDataReady())   
        {
			mTouch_Service();       
			if((mTouch_GetButtonState(touch) != MTOUCH_PRESSED))break;
		}
	}
	if(tempoDelay>=timeout)return 1;
	else return 0;
}

void delay_ms(unsigned int ms)
{
	unsigned int timeout=ms/INTERRUPTPERIOD;
	if(timeout>MAXDELAY)timeout=MAXDELAY;
	tempoDelay=0;
	while(tempoDelay<timeout);
}

void setupTimer1() {  
	TMR0IE = 1;	
	TMR1IE = 1;      		// abilito interrupt overflow timer1
	TMR1IF = 0;      		// resetto il flag di interrupt
	TMR1H = 60;    			// set high byte
	TMR1L = 176;    		// set low byte  (overflow ogni 50ms) 
	T1GCON = 0;      		// disabilito tutte le funzioni gate sul timer1
	T1CON = 0b00110001; 	// fosc/4, prescale=8, no LP, timer abilitato
	INTCON = 0b11000000;   	//abilito interrupt globali e periferici
	TMR1IF = 0;      		// resetto il flag di interrupt
}

void interrupt ISR(void)
{
    SAVE_STATE();                       // mTouch Framework-supplied general ISR save state macro. 
                                        // Not required, but convenient. 
	if(TMR1IF==1)
	{
		TMR1ON=0;									//fermo il timer1
		if(tempoDelay<MAXDELAY)tempoDelay++;		//incremento il tempo se posso
		if(tempoMotore<MAXDELAY && timerMotore)
			tempoMotore++;							//se il flag è attivo incremento il tempoMotore
		setupTimer1();								//resetto il timer1 ed il flag di interrupt
	}

	RESTORE_STATE();                    // mTouch Framework-supplied general ISR restore state macro. 
}

void System_Init() 
{
    OSCCON  = 0b11110000;       // 32 MHz Fosc w/ PLLEN_ON (config bit)  

    // mTouch sensor pins impostati come uscite digitali
    ANSELA  = 0b00000000;
    LATA    = 0b00000000;
    TRISA   = 0b00000000;
	WPUA	= 0;			//pull up disabilitate

	LEDS_OFF();				//led spenti
	MOTOR_OFF();			//relè motore off
	SWITCH_DOWN();			//relè switch off

    //la libreria Mtouch richiede l'utilizzo del timer0 ad 8bit
    OPTION_REG  = 0b10000000;   // TMR0 Prescaler  = 1:2
}

Qui è possibile scaricare il file HEX.

17 Risposte a “Touch Capacitivo per Tapparelle”

  1. ciao vorrei provarci anche io a realizzarlo ma non so dove cominciare per la parte sofwer potresti aiutarmi

    1. Ciao, dovrei sapere come sei attrezzato, hai un programmatore per i microcontrollori pic? Hai mai utilizzato un compilatore per microcontrollori pic?
      Ciao!

  2. Ciao, pure io sono a zero come software e, a dire il vero, non ho nemmeno il tempo per l’hardware. Sarei però disposto a concretamente ringraziare una eventuale realizzazione 🙂

  3. Impressionato!
    Complimenti 🙂

    A titolo di studio potresti inviarmi i sorgenti? Please!
    Mi sto avvicinando ora a questo tipo di hardware e mi interesserebbe capirne un bel po’ in piu’.

    1. Grazie dei complimenti! Visto che anche un altro utente mi ha richiesto il codice sorgente, per comodità ho deciso di pubblicarlo qui direttamente. Buon studio e buona programmazione!

      Ciao!

      Alberto

      1. Ciao Alberto, buongiorno.
        ho un paio di domande e spero tu possa aiutarmi.
        1) Ho visto che nella foto usi un pickit 3. Sono alla ricerca di un programmatore ma non mi è chiaro ancora su cosa indirizzarmi. la diofferenza fra il pickit 2 e 3? hai qualcosa che puoi consigliarmi?
        2) Circa il Tuo progetto, credi si possa eliminate l’intera parte dei trasformatori ed alimentare il tutto a 220V?

        Grazie 1000

        Ale

        1. Ciao Ale,
          per quanto riguarda il programmatore io mi trovo benissimo con il Pickit3 e te lo consiglio anche per quanto riguarda la futura compatibilità con nuovi microcontrollori, quindi se devi scegliere tra 2 e 3 prendi il 3 😉
          Premetto che il mio è un clone che vende la SureElectronics, costa un po’ meno ed è praticamente identico a quello che vende Microchip, anche i vari aggiornamenti software sono compatibili.
          Per quanto riguarda il secondo punto, io ho scelto di utilizzare un trasformatore per isolare in qualche modo tutto il circuito dalla tensione di rete, anche se nel mio progetto è stato interposto un vetro da 4, 5mm durante le fasi di assemblaggio/test e/o in caso di rottura del vetro volevo evitare che un contatto con le piastre di rame sottostanti potesse essere un pericolo.
          Se invece non hai problemi relativi alla sicurezza (es. circuito racchiuso in una scatola ben isolata) allora puoi tentare la strada di alimentare il tutto con tensione di rete senza l’ausilio di un trasformatore, ovviamente bisogna adattare le varie tensioni per i relè e per generare 5V per il microcontrollore. Ti consiglio questa application note della Microchip che parla appunto di sistemi trasformerless, sistemi di alimentazione senza trasformatore.

          Grazie della visita! a risentirci!

          Ciao

          Alberto

          1. Ciao e sempre grazie per le Tue risposte.

            ho trovato questo pickit3 http://www.sureelectronics.net/goods.php?id=1141 ma non capisco la differenza fra questo e quello che dichiarano faccia programmer e debugger. esteriormente sembrano identici. A differenza di quello della microchip qui sembra ci sia anche l’universal ZIF socket che non è da sottovalutare http://www.sureelectronics.net/goods.php?id=22.
            Ottendo una tua risposta per provvedere all’acquisto.
            Ottima l’application note allegata, grazie 1000

            Ale

          2. Io ho proprio questo del primo link che hai postato, è identico al pickit3 originale con tutte le funzionalità del pickit3 di microchip. Lo vendono assieme all’adattatore ed è utilissimo quando devi programmare manualmente qualche micro!

          3. Ciao, buonasera Alberto.

            Ho seguito il tuo consiglio ed ho preso il clone pickit3. credo a giorni mi verra’ consegnato.
            Al momento ho iniziato a scaricare il mplab x !!!
            Da panico, non sono neanche riuscito a compilare il tuo codice.
            Esistera’ qualche guida o qualche software piu’ semplice?
            Grazie
            Ale

          4. Io personalmente non sono ancora passato ad MplabX ma uso ancora la vecchia versione Mplab8… comunque il mio progetto necessita delle librerie mtouch di Microchip, le puoi scaricare da questo link.
            Come inizio non è dei più facili, anche perché devi configurare per bene Mplab per fargli conoscere dove sono le librerie da utilizzare una volta che le hai installate.
            Ti consiglio di cercare qualche tutorial online riguardo al classico “hello world” qualche lampeggio di un led, così prendi dimestichezza con l’ambiente di sviluppo e provi a compilare qualche pezzo di codice e programmare qualche microcontrollore con il tuo nuovo pickit3! 🙂

          5. Ciao Alberto, buongiorno.

            Ho ricevuto tutto il kit in settimana, a breve mi adoperero’ per capire il tutto.
            Al momento sono incastrato con il Tuo sorgente. Sto impazzendo 🙁
            ho installato: MikroC, MplabX, Mplab8 ma non sono riuscito a compilarlo con nesuuno dei 3, ho installato anche le librerie mTouch.
            Devo configurare qualcosa?
            fra le varie, in fase di compilazione, non mi trova un include p18cxxx.f.

            Grazie 1000
            Ale

          6. Ciao,
            come avevo accennato oltre ad installare le librerie bisogna anche includerle nel progetto:

            include mtouch

            Successivamente dal menù principale di MPLAB verifica di aver selezionato il corretto microcontrollore (PIC12F1840):

            Configure -> Select Device…

  4. Ciao,

    Mi dice che devo modificare il file mTouch_config.h al momento e’ configurato ad 8 sensori ed il pic utilizzato credo ne sopporti 4. credo vada a 2 vero?
    #define MTOUCH_NUMBER_SENSORS 2

    Ale

    1. Esatto, nel file mTouch_config.h oltre che ad impostare 2 sensori, si possono modificare diverse impostazioni per migliorare ed affinare la rilevazione capacitiva.

  5. Ciao Alberto, buon pomeriggio.
    Potresti pubblicare il file.hex da te compilato.
    ho un problema con la direttiva BORV_25. lo sto testando con il simulatore e quello compilato da me non si comporta proprio bene.

    Grazie 1000
    Ale

    1. Ho inserito un link al file HEX alla fine dell’articolo, basta cliccare con il tasto destro del mouse e scegliere “salva link con nome”.
      Per comodità lo riporto anche qui:

      Link al file HEX

      Ciao 🙂

I commenti sono chiusi.