DIY – Interrupteur télécommandé pour modélisme

avril 1st, 2013

Bon, si je me suis embêté à vous pondre une série d’articles sur la programmation AVR, c’est que j’avais une petite idée derrière la tête. En l’occurrence, j’avais besoin de pouvoir couper une alimentation embarquée dans un avion RC, bien sûr à distance.
L’idée était donc de réaliser un petit périphérique qui se connecte comme un servo-moteur standard de modélisme, mais qui active un relais en fonction de la valeur.

Déjà, il est important de savoir à quoi ressemble les signaux transmis par le récepteur RC aux servos :

Credit : http://nononux.free.fr

Credit : http://nononux.free.fr

Bon, il s’agit d’une sorte de PWM, mais avec un champs très limité car allant de 5 à 10% de la valeur. Dans mon cas, je ne suis intéressé que par 2 cas : On ou Off. Je décide donc de couper à 50%, de manière à pouvoir utiliser le manche des gaz en guise d’interrupteur : de 0 à 50% je suis Off, de 50% à 100% je suis On.
A partir de là, il y a plusieurs façons de voir les choses : il est possible de régler ça en analogique pur, mais j’avais peur que ce soit trop sensible aux éventuelles perturbations. (Et dans mon cas, je préférerais que ce ne soit pas sensible ;) ). Je suis donc partis sur la solution numérique pour traiter les impulsions.
Comme c’est pour embarquer dans un avion RC, il ne faut pas que ce soit lourd, donc j’ai choisi le micro-controlleur le plus petit possible, à savoir l’AtTiny85, que vous devez bien connaître désormais (voir ici, ici et ici), et qui plus est dans sa version CMS.

Le schéma

Le sch

Comme vous pouvez le constater sur le schéma ci-dessus, la partie électronique est réduite au strict minimum : Un régulateur de tension, pour fournir le 5v nécessaire à tout l’appareillage (servos, récepteur, etc…) dans le cas où l’on ne dispose pas de BEC (par exemple s’il n’y a pas de moteur). L’AtTiny85 dans sa configuration la plus simple (oscillateur interne), un mosfet pour piloter le relais, et le relais en lui même, petit relais 5v, capable de couper 175W quand même.
Le circuit a été réalisé sur un PCB de 0.8mm d’épaisseur, de manière, là encore à gagner du poids.

Vous l’aurez donc compris, dans ce montage, c’est le code qui fait tout le travail :

#include <avr/io.h>
#include <avr/interrupt.h>

//	   ___
//  PB5  *|+  |*  VCC
//  PB3  *|   |*  PB2
//  PB4  *|   |*  PB1   --> declenchement relais
//  GND  *|___|*  PB0   --> entrée PWM
//

volatile int count = 0; //le rapport cyclique
volatile int toff = 0;  //durée du signal à 0
volatile int ton = 0;	//durée du signal haut

int main(void)
{
	//configuration de la pin de sortie
	DDRB |= (1 << PORTB1); 	//on configure PB1 en tant que sortie
				//DDRB = Port B Data Direction Register

	//configuration du timer1 (Ton)
	TCCR0B |= (1 << CS00) | (1<<CS02); 	//Set up timer1 with prescaler 1/1024


	//configuration des interruptions
	GIMSK |= (1 << PCIE); 	//Enable pin change interrupt for PORTB 
				//GIMSK = General Interrupt Mask Register
				//PCIE = Pin Change Interrupt Enable

	PCMSK = (1 << PB0);  	//Enable pin change interrupt for PB0 (pcint0)
				//PCMSK = Pin Change Mask Register

	sei(); //mise en place des interrupts (set global interrupts)

	for(;;)
	{
		
		
		if(count>=7.5) //Si le rapport cyclique est > à 7 (Ton ~1.5ms)
		{
			PORTB |= (1 << PB1);
		}
		else
		{
			PORTB &= ~(1<<PB1);
		}
	}
}


ISR (PCINT0_vect) { //vecteur d'interruption
	if (PINB & (1<<PB0)) // detection de front montant
	{  
		
		toff = TCNT0; 	//Enregistrement de la valeur du timer Toff
		TCNT0 = 0;	//Réinitialisation du timer
	}
	else //detection de front descendant
	{
		ton = TCNT0;	//Enregistrement de la valeur du timer Ton
		TCNT0 = 0;	//Réinitialisation du timer
		if(toff)	//si on a déjà une valeur pour Toff
		{
			count = (ton*100L)/(ton+toff); //Le rapport cyclique = ton/(Ton+toff)
		}		
	}
} 

Voilà, il ne reste donc plus qu’à assembler tout ça, et à tester :

Le montage avec une led pour tester.

Le montage avec une led pour tester.

La chaîne complète, avec le récepteur

La chaîne complète, avec le récepteur

Et histoire de vérifier que tout fonctionne, une petite vidéo :

Voilà, un nouvel article prochainement pour vous faire voir l’utilisation réelle du bidule ;)
Ps : c’est un kit que vous retrouverez sur la boutique

DIY – Régulateur PWM

mars 25th, 2013

Dans la série montage à toujours avoir sous la main, je voudrais le régulateur de tension PWM !
Concrètement, ce montage permet de régler l’intensité lumineuse d’une ampoule ou d’une led, ou encore de régler la vitesse de rotation d’un moteur CC, en jouant sur la largeur des impulsions. Concrètement, la tension appliquée aux bornes de la charge ne change pas, mais on la laisse passer plus ou moins longtemps. Principal avantage, le rendement. Par exemple, si la charge que vous souhaitez piloter consomme beaucoup de courant, une régulation classique dissipera beaucoup de chaleur, ce qui ne sera pas le cas avec ce type de montage. Quelques explications.

modulation PWM

modulation PWM

Prenons une tension d’entrée (Vin) de 5v. Si la durée de la pulsation Ton est de 10ms, et Toff est de 10ms, alors la tension équivalente de sortie sera de Vin*(Ton/(Ton+Toff)), en l’occurrence 5*10/(10+10) =  2.5V. Comme je le disais au dessus, je parle bien de tension équivalente, car si vous mesurez la sortie avec un oscilloscope, vous verriez des créneaux 0-5v tels que présentés dans le dessin ci-dessus.
Maintenant qu’on a vu le fonctionnement, voyons le montage à proprement parlé :

Régulateur PWM

Régulateur PWM

Le coeur du montage est un NE555, qui génère des impulsions avec un rapport cyclique (rapport cyclique = Ton/Ton+Toff) variable. L’inconvénient de ce montage est que la fréquence varie légèrement lorsque l’on change le rapport cyclique. Ce n’est pas gênant pour contrôler l’intensité  d’une led ou la vitesse d’un moteur, mais si c’est pour faire des mesures d’efficacité par exemple, il faut en tenir compte.

La diode 1N4004 permet de brancher une charge inductive (moteur CC), en filtrant les retours de tensions. Le modèle de la diode peut être à adapter en fonction de la puissance moteur.

Le montage est prévu à la base pour une charge fonctionnant en 12v, avec une tension d’alimentation inférieure à 20 volts. Il est cependant tout à fait possible  d’utiliser des charges de 24v, avec des tensions d’alimentations supérieures (max 37v), en prenant soin de mettre une résistance bobinée de 220 ohms en R5, afin d’éviter que le LM317 n’ai trop de chaleur à dissiper (ceci dit, il n’alimente que le NE555, donc la consommation est assez réduite). Dans le cas standard, cette résistance est inutile.

Voici le résultat une fois monté sur un joli PCB :

Le résultat final

Le résultat final

Une petite vidéo du montage en fonctionnement :

Je profite de cet article pour inaugurer une nouvelle rubrique à ma boutique, à savoir les Kits ! Vous y retrouverez au fur et à mesure certains des montages déjà présentés ici (dont ce montage), et bien sur tous ceux à venir que je jugerais intéressants :)

Programmation Avr, dernière partie

mars 17th, 2013

Ok, trois articles sur le sujet ça peut paraître court, mais ça constitue déjà une bonne introduction, qui devrais vous permettre d’envisager la suite par vous-même. Nous allons aujourd’hui nous pencher sur un autre élément essentiel de la programmation avr :

Les interruptions

Imaginez que vous êtes en train de souder un circuit quand tout à coups la sonnette de votre porte d’entrée résonne. Vous pouvez arrêter ce que vous étiez en train de faire (mais rien ne vous y oblige), aller répondre, et revenir à vos soudures. Et c’est exactement comme ça que se passe une interruption dans le monde informatique, ici représentée par la sonnette.

Les interruptions peuvent être matérielles (changement d’état d’une broche, timer qui arrive à une certaine valeur), ou logicielles, et le nombre d’interruption disponibles dépend du modèle d’avr.
Les différentes interruptions disponibles sur votre microcontrolleur sont visibles sur la table des vecteurs d’interruptions de la datasheet (ici, je suis toujours sur l’Attiny85)
Interrupt vectors

Vecteurs d’interruption

Lorsqu’une interruption se produit, l’avr stoppe ce qu’il était en train de faire pour exécuter  la fonction que vous souhaitiez rattacher à cette interruption. Pour ce faire, il utilise une table des vecteurs d’interruption, positionnée au début de sa mémoire flash, afin de faire la correspondance Interruption <–> fonction.

Afin d’utiliser une interruption sur notre avr, nous avons besoin de faire 3 choses :

  • Positionner le bit Enable Interrupt (en général avec la fonction sei(), set global interrupt, mais peut aussi être positionné à la main)
  • Positionner les bits de chaque interruption.
  • et enfin remplir la condition de l’interruption.

Comme d’habitude, nous allons voir ensemble un petit exemple. Ce programme servira à compter les impulsions reçues sur la pin 5 de l’Attiny85. Lorsqu’il arrivera à 200 ou plus, il allumera une led sur la pin 6. Les impulsions pourront être crées avec un bouton poussoir (attention au debounce) ou un générateur de signal.

#include <avr/io.h>
#include <avr/interrupt.h>

//	   ___
//  PB5  *|+  |*  VCC
//  PB3  *|   |*  PB2
//  PB4  *|   |*  PB1   --> sortie led
//  GND  *|___|*  PB0   --> entrée surveillée
//

volatile int count = 0; //compte des interrupts


int main(void)
{
	//configuration de la pin de sortie
	//configuration des interruptions
		//Positionnement du Global Interrupt MaSK register
		//Positionnement du Pin Change Mask Register
		//mise en place des interrupts (set global interrupts)

	for(;;)
	{
		
		
		//Si on a eu 200 impulsions ou plus
		{
			//on alume la led
		}
		//sinon
		{
			//On éteind la led
		}
	}
}


ISR (PCINT0_vect) { //vecteur d'interruption
	// detection de front montant
	{  
		//on ajoute 1 au décompte
	}
	//detection de front descendant
	{
		//ici on ne fais rien, juste pour l'exemple...
	}
} 

Voilà, déjà, on peut remarquer en fin de code la façon dont est définie le vecteur d’interruption. Un autre détail à remarquer est la déclaration de ma variable count. Cette variable étant utilisée à la fois par mon programme principal et par ma fonction, il est impératif de la déclarer en volatil, sous peine de ne jamais la voir s’incrémenter.
Voyons voir maintenant comment déclarer nos interruptions (encore une fois, les valeurs des bits sont tirés de la datasheet, cf page 53, chapitre 9.3.2) :

#include <avr/io.h>
#include <avr/interrupt.h>

//	   ___
//  PB5  *|+  |*  VCC
//  PB3  *|   |*  PB2
//  PB4  *|   |*  PB1   --> sortie led
//  GND  *|___|*  PB0   --> entrée surveillée
//

volatile int count = 0; //compte des interrupts


int main(void)
{
	//configuration de la pin de sortie
	//configuration des interruptions
		//Positionnement du Global Interrupt MaSK register
                GIMSK |= (1 << PCIE); 	//Enable pin change interrupt for PORTB 
		    		        //GIMSK = General Interrupt Mask Register
				        //PCIE = Pin Change Interrupt Enable
		//Positionnement du Pin Change Mask Register
                PCMSK = (1 << PB0);  	//Enable pin change interrupt for PB0 (pcint0)
		  		        //PCMSK = Pin Change Mask Register
		//mise en place des interrupts (set global interrupts)
                sei();

	for(;;)
	{
		
		
		//Si on a eu 200 impulsions ou plus
		{
			//on alume la led
		}
		//sinon
		{
			//On éteind la led
		}
	}
}


ISR (PCINT0_vect) { //vecteur d'interruption
	// detection de front montant
	{  
		//on ajoute 1 au décompte
	}
	//detection de front descendant
	{
		//ici on ne fais rien, juste pour l'exemple...
	}
} 

Quelques petites explications complémentaires s’imposent ici. J’ai décidé de dédier une pin de mon Attiny85 à la surveillance du signal d’entrée, j’ai donc utilisé les Pin Change Interrupt. Mais si j’avais voulu utiliser ma broche pour d’autres choses en parallèle, j’aurais du utiliser les External Interrupt Request (donc positionner le bit INT0 au lieu de PCIE). Il faut également noter que par défaut, une interruption ne peut en interrompre une autre (comprendre : les interruptions sont désactivées le temps du traitement du vecteur d’interruption actuel). Il est cependant possible (mais pas franchement recommandé) de les réactiver en réutilisant sei() à l’intérieur de la déclaration du vecteur d’interruption. De la même manière, si vous souhaitez qu’une portion de votre code ne soit interrompue sous aucun prétexte, vous pouvez utiliser la fonction cei().
Voici maintenant le code complet :

#include <avr/io.h>
#include <avr/interrupt.h>

//	   ___
//  PB5  *|+  |*  VCC
//  PB3  *|   |*  PB2
//  PB4  *|   |*  PB1 
//  GND  *|___|*  PB0   --> entrée surveillée
//

volatile int count = 0; //compte des interrupts


int main(void)
{
	//configuration de la pin de sortie
	DDRB |= (1 << PORTB1); 	//on configure PB1 en tant que sortie
				//DDRB = Port B Data Direction Register

	//configuration des interruptions
	GIMSK |= (1 << PCIE); 	//Enable pin change interrupt for PORTB 
				//GIMSK = General Interrupt Mask Register
				//PCIE = Pin Change Interrupt Enable

	PCMSK = (1 << PB0);  	//Enable pin change interrupt for PB0 (pcint0)
				//PCMSK = Pin Change Mask Register

	sei(); //mise en place des interrupts (set global interrupts)

	for(;;)
	{
		
		
		if(count>=200) //Si on a eu 200 impulsions ou plus
		{
			PORTB |= (1 << PB1);
		}
		else
		{
			PORTB &= ~(1<<PB1);
		}
	}
}


ISR (PCINT0_vect) { //vecteur d'interruption
	if (PINB & (1<<PB0)) // detection de front montant
	{  
		count = count++;
	}
	else //detection de front descendant
	{
		//ici on ne fais rien, juste pour l'exemple...
	}
} 

Bon, passons sur les modifications d’état de la led, déjà abordées auparavant. Il est ici intéressant de noter comment se fait la détection d’un front montant ou descendant : à la suite d’un changement d’état, on lit l’état de la pin PB0, si elle est à l’état haut c’était un front montant, sinon, un front descendant.
Voilà, c’était le dernier article de cette série, qui sera suivi très bientôt d’une application concrète :)

Un petit parfum d’antan…

mars 11th, 2013

Des fois sur Ebay, on tombe sur de petites merveilles… J’ai commandé récemment des tubes en provenance directe d’un pays de l’ex-URSS, et voici à quoi ressemblais le contenu une fois son emballage de protection enlevé :

Boite d'origine

Boite d’origine

Une boite de tubes d’origine, jamais ouverte, et datant de 1973 :)

Et voici comment était emballés les tubes à l’intérieur :

P1020004

Le petit détail sympa : chaque tube est accompagné de sa datasheet imprimée (en russe ;) )

P1020005

(Ah et si y’en a qui se posent la question, par curiosité je les ai passés au compteur geiger (provenance ukraine) et…. rien du tout :) )

DIY – Bureau d’électronique sur mesure

février 25th, 2013

Dans les premiers articles que j’écrivais sur ce blog, je vous présentais un labo mobile d’électronique, qui me permettait de tout concentrer dans une petite boite transportable, et surtout de tout replier après usage. Le temps passant, mon activité autour de l’électronique s’est faite de plus en plus marquée, et, logiquement, la place occupée a augmentée de manière exponentielle…. A tel point que le petit labo mobile n’était plus qu’une étagère d’un énorme fatras entassé plus ou moins comme je pouvais (comme me le faisait remarquer un ami, on le voyais même plus sous les fils !). Bref, le waf venait d’en prendre un sérieux coups !
J’ai donc commencé à regarder ce que je pouvais mettre en place comme solution de remplacement et rapidement j’ai constaté que les solutions du commerce ne me convenais pas : la surface au sol que je pouvais me permettre d’occuper était trop limitée pour pouvoir envisager des bureaux de type industriels, et seuls quelques meubles informatiques qui rentraient étaient des meubles d’angle assez mal foutus. Histoire de corser le tout, je ne désespère pas de déménager sous relativement court terme, il fallait donc que ce bureau soit facilement démontable (exit donc ikea et compagnie, il faut qu’il puisse se remonter ensuite !) et surtout qu’il soit modulable, de manière à l’adapter à un nouvel environnement où j’aurais logiquement plus d’espace.

J’étais tombé sur cet article il y a quelques temps, qui m’avais beaucoup inspiré, et j’avais envie de mettre ce concept en pratique, c’était là l’occasion revée.

Le matériel de base

Le matériel de base

Je suis donc partis sur l’idée de construire ce bureau en profilé aluminium. Ce type de montage combine plusieurs avantages : coût assez raisonnable (pour le profilé en tous cas), solidité de la structure, les rainures dans le profilé alu me donnent plein d’idées, démontable et remontable sans soucis, et modulable à l’infini.
Coté équipement, pas besoin d’énormément d’outillage : des profilés alu de 20mm (comme ceux utilisé sur les reprap Prism), des équerres, des écrous, les vis qui vont bien, et une clé BTR. Au passage, comme on peut le voir ci-dessus, j’ai utilisé des écrous un peu spéciaux : ils sont équipés d’une petite bille poussée par un ressort. L’avantage, c’est qu’on peu enquiller l’écrou dans un profilé mis à la verticale, il ne bougera pas, mais on peut le faire glisser simplement pour l’emmener là où l’on veux. Son inconvénient, pas contre, c’est son prix : les écrous à eux seuls représentent quasiment la moitié du coût du bureau :( Bref, si vous voulez une solutions low-cost, vous savez où économiser (mais si vous aimez pas vous prendre la tête, n’hésitez pas, ils sont pour vous)

Vue d'ensemble du bureau

Vue d’ensemble du bureau

Quelques heures de montage plus tard, le bureau est fonctionnel. Le plateau a été usiné à la fraiseuse CNC, avec des emplacements pour les montants, et des trous fraisés pour les vis de fixation, de manière a ne pas avoir de tête de vis qui dépassent (Merci à l’équipe de Ginova pour le coups de main :) )

Après cette présentation rapide, passons directement aux petits bonus !

Support aimanté pour tournevis

Support aimanté pour tournevis

Sur mon labo mobile, un des trucs que je trouvais vraiment pratique, c’était les aimants pour fixer mes tournevis. Je tenais absolument à retrouver ça sur ce bureau, j’ai donc créé une petite pièce en PLA dans laquelle vient se sertir un aimant. La pièce viens s’emmancher dans la rainure du profilé, et peut donc coulisser sur toute la longueur, de manière à ne pas gêner en étant au mauvais endroit au mauvais moment.

Boite de rangement

Boite de rangement

Deuxième bonus : des boîtes de rangement qui s’enfichent dans les profilés. Je peut les positionner où je veux sur la structure, et les faire glisser au besoin. Ca me permet de faire des rangements par type d’activité (CMS, général, etc…) et de ne placer devant moi que celle(s) qui est utile. Ca, je me suis vite rendu compte que ça allais me changer la vie :)
Accessoirement, ça me permet aussi, lors d’un démontage, d’y placer toutes les petites vis et de les retrouver ensuite…

La tablette et les boites de rangement

La tablette et les boites de rangement

Sur la photo du dessus, on peut voir les boites positionnées en mode « rangé », quand je les utilises, elles sont placées face à moi.
Le dernier bonus, c’est la tablette, qui me permet d’afficher les datasheets des composants où les schémas sans avoir besoin de trouver un moyen de caler mon portable à coté du bureau (il prend vraiment trop de place sur le bureau). J’ai prévu de lui réaliser un bras pliant, mais ça sera pour dans un second temps.

Les fichiers STL de mes boites et supports d’aimants :
tarBoite_composants_1.3.STL

 

tarSupport_aimant.STL