Mercredi, juillet 30 2014

WebRadioRéveilWifi -2-

Suite de l'étude précédente :

Nouveau billet d'étape, cette fois-ci concernant l'horloge, et je me rend compte que je n'ai pas encore présenté le projet complet, oups !
Bon je verrais ça plus tard avec un billet N° zero…

  • Donc après les quelques tests réalisés sur le Raspberry pi pour la partie WebRadio, on va s'occuper ici de la partie horloge.

Au départ je voulais la faire avec un µC Atmega, et puis comme ça sans trop réfléchir, je me suis procuré un Arduino.
Je n'avais jusqu'alors pas essayé, considérant que l’utilisation d'un µC était finalement la même chose, en bas niveau il s'entend.
Sauf que j'avais tord ! Pas sur le fond, puisque c'est bel et bien le cas, mais sur la forme. En effet programmer un AVR n'a rien de sexy, et lorsqu'on connaît mal le composant, il faut beaucoup de temps et de persévérance avant de savoir ce qu'il est possible de faire et d'en appréhender le fonctionnement, notamment le plus complexe pour moi qui ne suis pas codeur, la programmation.
Je me voyais donc mal barré, et s'il y a bien une chose fondamentale que j'ai apprise, c'est qu'il faut avant tout se faire plaisir pour avancer.
Il me fallait donc emprunter une voie différente, et de découvrir l'Arduino et son langage simplifié aura débloqué la situation.
J'ai donc été très surpris de parvenir à faire fonctionner mon horloge en à peine un week-end, fort des nombreux exemples et réalisations documentées en ligne.
j'aurais dû essayer Arduino plus tôt ^^;
J'ai ensuite pris plaisir à continuer de perfectionner mon système pour y ajouter des fonctionnalités, que je vais détailler ici.


Premiers essais, premières erreurs :

  • Le système d'affichage repose sur des registres à décalages. J'avais d'abord entrepris les 74HC164, car j'en avais sous la main.

Sauf que, voici le résultat :

Comme diraient nos amis anglo-saxon, ça « flicke », et ce à chaque boucle du programme, plus ou moins vite en fonction de sa vitesse d'exécution, que j'ai réglé ici à 1/4 de secondes pour qu'on voit bien le résultat.
J'ai perdu pas mal de temps à chercher dans mon code ce qui n'allait pas, avant de constater que ce comportement était dû à la nature du registre, qui ne dispose pas de fonction Latch permettant d'interrompre la transmission de donnée.

  • J'ai alors opté pour des 74HC595…

Le montage :

Voici le schéma structurel :
horloge-structurel-0.1.png

  • On a donc l'Arduino connecté à un module chronodot, et à 4 afficheurs 7 segments via des registres à décalages.

Oui j'ai omis volontairement de mettre des résistances de protection sur chaque segments, et les résistances de polarisation des transistors, je verrais ça plus tard.
Pour le moment c'est du prototype, donc voilà, et puis ces afficheurs mangent du 4,3V sur les 5V de l'alimentation, ce qui laisse très peu d'énergie néfaste aux diodes, d'autant qu'on va les utiliser en PWM.

  • La maquette sur plaque labo :

dsc00056.jpg dsc00070.jpg

  • Le composant DS3231, ainsi câblé forme le module chronodot, qu'il me suffit d'enficher dans une plaquette labo. Une library assez simple pour s'adresser à ce composant existe, il faut donc l'installer dans le logiciel Arduino.

dsc00074.jpg dsc00058.jpg

dsc00069.jpg

Le développement :

Ce qui me paraissait une montagne obscure et sombre à franchir, quoique bien éclairée par la plateforme Arduino n'a pas été franchie d'un seul coup, et le programme que vous trouverez plus loin s'est construit par petits bouts de codes que j'ai ensuite assemblés et fait évoluer, en m'aidant d'exemples Arduino pour l'affichage sur les 7 segments, et de l'exemple fournit avec la librairie pour le chronodot, le circuit électronique allant en se complexifiant.

Étape après étape on va se rapprocher de l'objectif :

  • Partie afficheurs,

- Allumer une led (exemple arduino).
- Allumer un afficheur.
- Afficher le chiffre de mon choix sur l'afficheur (datasheet 74HC164).
- Afficher un compte à rebours sur un afficheur.
- Ajouter un second afficheur, et afficher un nombre.
- Faire varier l'intensité d'une LED avec la PWM (exemple arduino).
- Modification du circuit avec transistor pour utilisation de la PWM avec les afficheurs.
- PWM fixée sur l'intensité de mon choix dans le code.

  • Module chronodot,

- Câblage du module chronodot et connexion à l'Arduino (datasheet DS3231).
- Récupération de l'heure et affichage dans la console série Arduino (exemple lib chronodot).

  • Affichage de l'heure,

Ça se complique, c'est le passage avec lequel j'ai eu le plus de mal et qui m'aura donné des rêves étrange entre samedi et dimanche.

- Affichage des secondes sur deux afficheurs (brainstorming).
- Simplification de ce code à l'aide d'un tableau.
- Fixé dans le code, affichage au choix, soit des heures, minutes ou secondes.

Bloqué sur le problème de flicker, fin du week end.

- Lundi, remplacement des 74HC164 pour les 74HC595, flicker out, ouf ^^
Plus tard,
- Ajout d'un bouton poussoir, allumer une led quand on le presse (exemple arduino).

Je suis resté un peu bloqué car je ne comprenais pas comment utiliser la librairie chronodot, alors qu'il suffit de décrypter le fichier Chronodot.h pour comprendre ce que la librairie permet de faire.

- Mise à l'heure le chronodot à l'aide de deux boutons poussoir.

  • La plaque labo étant trop étroite, câblage sur plaque d'essais à trou.

dsc00076.jpg dsc00077.jpg dsc00079.jpg dsc00080.jpg
- Affichage des heures et secondes, mise à l'heure manuelle ok.

  • PWM automatique,

- Câblage de la photodiode et affichage dans la console série Arduino de la valeur renvoyée par la diode (exemple arduino).
- Variation de la PWM en fonction de la valeur envoyée par la photodiode, dans le but de baisser l'intensité lumineuse des afficheurs dans la pénombre, et de l'augmenter quand il fait soleil.

C'est tout pour le moment !

  • Il me reste à voir comment implémenter le système pour les alarmes du réveil, et à communiquer certains événements avec la Raspberry et je pense que ce sera tout pour cette partie du projet.

Voici le programme, dont j'ai commenté chaque ligne afin de ne pas perdre les débutants.

/****** Domaine publique, youpi ! ******/
#include <Wire.h>       // Communication avec le RTC
#include "Chronodot.h"  // Fonctions du Chronodot
 
/****************/
/* Déclarations */
/****************/
 
/****** Signaux ******/
#define datapin 10   // pin 10 pour les données vers les registres à décallages
#define clockpin 11  // pin 11 pour l'horloge qui coordonne les registres à décallages
#define latchpin 8   // pin 8 pour le déclencheur des registres à décallages
 
/****** Boutons poussoir ******/
#define BoutonMinutes 12    // pin 12 pour le bouton poussoir d'incrément des minutes
#define BoutonHeures 13     // pin 13 pour le bouton poussoir d'incrément des heures
#define BoutonShift 7       // pin 7 pour le bouton poussoir shift
int EtatBoutonMinutes = 1;  // variable pour stocker l'état du bouton aprés sa lecture
int EtatBoutonHeures = 1;   // variable pour stocker l'état du bouton aprés sa lecture
 
/****** Alimentation des 7 segments en PWM ******/
#define ledPin 9                    // pin 9 pour le signal PWM de cadencement des afficheurs et leds
#define photodiodepin 0             // pin A0 pour la photodiode
unsigned int ValeurPhotoDiode = 0;  // variable pour stocker l'état de la photodiode aprés sa lecture
 
/****** Variables temporelles ******/
unsigned int heures;    // pour stocker les heures
unsigned int heuresINC; // pour stocker l'incrément des heures
unsigned int minutes;   // pour stocker les minutes
unsigned int minutesINC;// pour stocker l'incrément des minutes
unsigned int secondes;  // pour stocker les secondes
unsigned int annee;     // pour stocker l'annee
unsigned int mois;      // pour stocker le mois
unsigned int jour;      // pour stocker le jour
Chronodot HORLOGE;      // HORLOGE, nom choisis arbitrairement, référence à la librairie Chronodot
 
/****** Variables d'affichage ******/ 
int dizH = 0;          // pour stocker les dizaine des heures
int unitH = 0;         // pour stocker les unités des heures
int dizM = 0;          // pour stocker les dizaine des minutes
int unitM = 0;         // pour stocker les unités des minutes
byte AfficheurUN;      // données binaire pour l'afficheur UN, situé le plus à droite
byte AfficheurDEUX;    // données binaire pour l'afficheur DEUX
byte AfficheurTROIS;   // données binaire pour l'afficheur TROIS
byte AfficheurQUATRE;  // données binaire pour l'afficheur QUATRE, situé le plus à gauche
byte dataArray[10];    // Tableau de données
 
/*******************/
/* Initialisations */
/*******************/
void setup ()      // Fonction d'initialisation obligatoire
{
  dataArray[0] = B00000011;  // Case du tableau qui contient la valeur binaire pour afficher zero sur un afficheur 7 segments
  dataArray[1] = B10011111;  // Case du tableau qui contient la valeur binaire pour afficher un sur un afficheur 7 segments
  dataArray[2] = B00100101;  // Case du tableau qui contient la valeur binaire pour afficher deux sur un afficheur 7 segments
  dataArray[3] = B00001101;  // Case du tableau qui contient la valeur binaire pour afficher trois sur un afficheur 7 segments
  dataArray[4] = B10011001;  // Case du tableau qui contient la valeur binaire pour afficher quatre sur un afficheur 7 segments
  dataArray[5] = B01001001;  // Case du tableau qui contient la valeur binaire pour afficher cinq sur un afficheur 7 segments
  dataArray[6] = B01000001;  // Case du tableau qui contient la valeur binaire pour afficher six sur un afficheur 7 segments
  dataArray[7] = B00011111;  // Case du tableau qui contient la valeur binaire pour afficher sept sur un afficheur 7 segments
  dataArray[8] = B00000001;  // Case du tableau qui contient la valeur binaire pour afficher huit sur un afficheur 7 segments 
  dataArray[9] = B00001001;  // Case du tableau qui contient la valeur binaire pour afficher neuf sur un afficheur 7 segments 
 
  pinMode(clockpin, OUTPUT);     // pin correspondant à "clockpin" initialisée en sortie
  pinMode(datapin, OUTPUT);      // pin correspondant à "datakpin" initialisée en sortie
  pinMode(latchpin, OUTPUT);     // pin correspondant à "latchpin" initialisée en sortie
  pinMode(BoutonMinutes, INPUT); // pin correspondant à "BoutonMinutes" initialisée en entrée 
  pinMode(BoutonHeures, INPUT);  // pin correspondant à "BoutonHeures" initialisée en entrée     
 
  Wire.begin();     // initialisation du chronodot, référence à la librairie wire
  HORLOGE.begin();  // initialisation du chronodot, référence à la librairie Chronodot
 
//************ MISE à L'heure du module RTC DS3231 ************
  HORLOGE.adjust(DateTime(2014,12,25,10,30,12));  // années, mois, jour, heures, minutes, secondes
}
 
/*************/
/* Programme */
/*************/
void loop ()      // boucle du programme !
{
  horloge ();                // appelle la fct "horloge", récupération des données temporelles
  affiche ();                // appelle la fct "affiche", transfert des données temporelles sur les afficheurs 7 segments
  SurveilleBoutonHeures ();  // appelle la fct "SurveilleBoutonHeures", incrémente les heures si appuyé  
  SurveilleBoutonMinutes (); // appelle la fct "SurveilleBoutonMinutes", incrémente les minutes si appuyé  
  AjusteLuminosite();        // appelle la fct "AjusteLuminosite", plus il fait sombre, plus la lumière des afficheurs baisse
}
 
/***** Fonction d'horloge *******/   
void horloge ()
{
  DateTime now = HORLOGE.now();  // lecture de l'heure en cours dans la puce DS3231, référence à la librairie Chronodot
  heures = now.hour(), DEC;      // stocke l'heure en décimale dans la variable "heures" grace à la fct "hour" de la lib chronodot
  minutes = now.minute(), DEC;   // stocke les minutes en décimale dans la variable "minutes" grace à la fct "minute" de la lib chronodot
  secondes = now.second(), DEC;  // stocke les secondes en décimale dans la variable "secondes" grace à la fct "second" de la lib chronodot
  annee = now.year(), DEC;       // stocke l'année en décimale dans la variable "annee" grace à la fct "year" de la lib chronodot
  mois = now.month(), DEC;       // stocke le mois en décimale dans la variable "mois" grace à la fct "month" de la lib chronodot 
  jour = now.day(), DEC;         // stocke le jour en décimale dans la variable "jour" grace à la fct "day" de la lib chronodot
}
 
/***** Fonction d'affichage sur les 7 segments *******/  
void affiche ()
{
  dizH = heures / 10;   // par calcul, extrait la dizaine de "heures" et stocke le résultat dans "dizH" 
  unitH = heures % 10;  // par calcul, extrait l'unités de "heures" et stocke le résultat dans "unitH" 
  dizM = minutes / 10;  // par calcul, extrait la dizaine de "minutes" et stocke le résultat dans "dizM"   
  unitM = minutes % 10; // par calcul, extrait l'unité de "minutes" et stocke le résultat dans "dizM" 
 
  AfficheurUN = dataArray[unitM];    // stocke la valeur binaire 7 segments de l'unité de minutes dans "AfficheurUN"
  AfficheurDEUX = dataArray[dizM];   // stocke la valeur binaire 7 segments de la dizaine de minutes dans "AfficheurDEUX"
  AfficheurTROIS = dataArray[unitH]; // stocke la valeur binaire 7 segments de l'unité d'heures dans "AfficheurTROIS"
  AfficheurQUATRE = dataArray[dizH]; // stocke la valeur binaire 7 segments de la dizaine d'heures dans "AfficheurQUATRE"
 
  digitalWrite(latchpin, 1);                              // latch à l'état HAUT pour autoriser le transfert des données série   
  shiftOut(datapin, clockpin, LSBFIRST, AfficheurUN);     // envoi l'unités minute au registre à décallage
  shiftOut(datapin, clockpin, LSBFIRST, AfficheurDEUX);   // envoi la dizaine minute au registre à décallage
  shiftOut(datapin, clockpin, LSBFIRST, AfficheurTROIS);  // envoi l'unités heure au registre à décallage
  shiftOut(datapin, clockpin, LSBFIRST, AfficheurQUATRE); // envoi la dizaine heure au registre à décallage  
  digitalWrite(latchpin, 0);                              // latch à l'état BAS pour arreter le transfert des données série  
}
 
/***** Fonction Surveillance du BoutonHeures *******/        
void SurveilleBoutonHeures ()
{ 
  EtatBoutonHeures = digitalRead(BoutonHeures);  // Lit l'état du bouton (appuyé ou relaché) et stocke la valeur dans la variable "EtatBoutonHeures"
  if (EtatBoutonHeures == LOW)   // si le bouton est appuyé
    {  
    delay(170);                  // alors, attendre 170 ms, permet un appuie bref pour incrémenter de 1, et un appuie long pour incrémenter rapidement d'autant qu'on veut
    RegleHeures ();              // et appeller la fonction "RegleHeures"
    }  
}
 
/***** Fonction Surveillance du BoutonMinutes *******/        
void SurveilleBoutonMinutes ()
{ 
  EtatBoutonMinutes = digitalRead(BoutonMinutes);  // Lit l'état du bouton (appuyé ou relaché) et stocke la valeur dans la variable "EtatBoutonMinutes"
  if (EtatBoutonMinutes == LOW)    // si le bouton est appuyé
    {  
    delay(170);                    // alors,  attendre 170 ms, permet un appuie bref pour incrémenter de 1, et un appuie long pour incrémenter rapidement d'autant qu'on veut
    RegleMinutes ();               // et appeller la fonction "RegleMinutes"
    }  
}
 
/***** Fonction d'incrément Heures *******/ 
void RegleHeures ()
{ 
  heuresINC = heures + 1;  // additionne 1 à la valeur contenue dans la variable "heures" et stocke le résultat dans la variable "heuresINC"
  if (heuresINC > 23)      // si la valeur de "heuresINC" dépasse 23 (23h)
  {
    heuresINC = 0;         // alors, et la variable "heuresINC" à zero (minuit)
  }
    HORLOGE.adjust(DateTime(annee,mois,jour,heuresINC,minutes,0));  // récup des données temporelles depuis les différentes variables pour mise à l'heure la puce DS3231, secondes à zero
}
 
/***** Fonction d'incrément minutes *******/ 
void RegleMinutes ()
{ 
  minutesINC = minutes + 1;  // additionne 1 à la valeur contenue dans la variable "minutes" et stocke le résultat dans la variable "minutesINC"
  if (minutesINC > 59)      // si la valeur de "minutesINC" dépasse 59 (59min)
  {
    minutesINC = 0;         // alors, met la variable "minutesINC" à zero
  }
    HORLOGE.adjust(DateTime(annee,mois,jour,heures,minutesINC,0));  // récup des données temporelles depuis les différentes variables pour mise à l'heure la puce DS3231, secondes à zero
 }
 
 /***** Fonction d'ajustement automatique de la luminosité des afficheurs *******/ 
void AjusteLuminosite()
{
  ValeurPhotoDiode = analogRead(photodiodepin);  // Lit la valeur renvoyée par la photodiode, et stocke la valeur dans la variable "ValeurPhotoDiode"
  if (ValeurPhotoDiode > 500)       // si la valeur est supérieure à 500 (beaucoup de lumière reçue, genre en plein jour)
  {
     analogWrite(ledPin, 255);      // alors, illumination des afficheurs et leds à 100% (PWM de 0 à 255)
  }
  else if (ValeurPhotoDiode > 400)  // sinon, si la valeur est supérieure à 400
  {
    analogWrite(ledPin, 212);       // alors, illumination des afficheurs et leds moins forte    
  }
  else if (ValeurPhotoDiode > 300)  // sinon, si la valeur est supérieure à 300
  {
    analogWrite(ledPin, 169);       // alors, illumination des afficheurs et leds moins forte 
  }
  else if (ValeurPhotoDiode > 200)  // sinon, si la valeur est supérieure à 200
  {
    analogWrite(ledPin, 127);       // alors, illumination des afficheurs et leds moins forte 
  }
  else if (ValeurPhotoDiode > 100)  // sinon, si a valeur est supérieure à 100
  {
    analogWrite(ledPin, 83);        // alors, illumination des afficheurs et leds moins forte 
  }
  else                              // sinon,  (très peu voire pas du tout de lumière reçue, genre dans la nuit)
  {
    analogWrite(ledPin, 40);        // alors, illumination des afficheurs et leds aux minimum
  } 
}


À suivre…


Ressources :

- http://pichonjulien.blogspot.fr/2009/11/pilotage-dun-afficheur-7-segments.html
- http://home.roboticlab.eu/fr/examples/display/segment_display
- http://www.sonelec-musique.com/electronique_theorie_afficheurs_led.html
- http://www.robot-maker.com/index.php?/tutorials/article/41-composant-les-afficheurs-7-segments/
- http://www.pobot.org/Piloter-des-afficheurs-7-segments.html
- http://playground2014.wordpress.com/arduino/1-3-7-segment-display/
- http://www.wikidebrouillard.org/index.php/Afficheur_7_segments_pilot%C3%A9_par_Arduino
- http://www.instructables.com/id/Different-methods-of-driving-7-Segment-LED-display/?ALLSTEPS
- http://www.sonelec-musique.com/electronique_realisations_afficheur_leds_7seg_007.html
- http://www.instructables.com/id/The-74HC164-Shift-Register-and-your-Arduino/?ALLSTEPS
- http://www.instructables.com/id/Multiplexing-with-Arduino-and-the-74HC595/?ALLSTEPS
- http://wiki.t-o-f.info/Arduino/ExempleD%C3%A9multiplexeurNum%C3%A9rique74HC595

- http://docs.macetech.com/doku.php/chronodot_v2.0
- http://schazamp.wordpress.com/2010/01/21/chronoblot/
- http://homecoder.wordpress.com/2013/12/12/getting-to-grips-with-a-real-time-clock/
- http://skyduino.wordpress.com/2012/01/07/tutoriel-arduino-horloge-rtc-ds1307-librairie-liquidcrystal/

- http://www.bricobidules.com/index.php?post/2012/04/29/iTime%2C-une-horloge-sous-Arduino-dans-un-bo%C3%AEtier-de-Mac-Mini
- http://www.instructables.com/id/Arduino-based-clock/
- http://kevinrye.net/electronics/source/

Lundi, juillet 28 2014

Une Borne d'Arcade maison, PS

  • Il est des jours comme ça, où lors d'un surf incité par les stats du blog, puis au détour d'un forum, on se retrouve à tomber sur un stock de photos pour le moins impressionnantes.

Pas d'articles ou de notes associés qui détaillent la fabrication de cette borne d'arcade, mais juste le compte de page perso free. http://famillemafieuse.free.fr/borneArcade/photos/

  • Le système de rotation est tout bonnement très ingénieux et d'une simplicité telle que je me fais un plaisir de relayer ici ces travaux qui m'ont laissés pantois…

À y repenser, si j'avais eu connaissance d'un tel système, je l'aurais adopté direct pour ma borne !!
Après analyse ce système semble tellement évident qu'on se demande pourquoi je n'y ai pas pensé, encore faudrait-il avoir intégré dans mon schéma de pensée, la compétence soudure métallique, afin de pouvoir raisonner jusque là.
Maintenant que je sais un peu souder, le champ des possibles est bien plus large qu'auparavant, je le comprend avec cette borne que je vous laisse découvrir tranquillement…

Le Support rotatif du téléviseur :

Une roue de vélo, quatre roues de rollers, et un cadre métallique… Il fallait y penser !
ch.jpg cj.jpg
ci.jpg cl.jpg cm.jpg cr.jpg

Avec deux barres supplémentaires pour recevoir le chassis électronique de la télé, voici le système de rotation au complet pour essais.
cs.jpg ef.jpg
eg.jpg ia.jpg
ib.jpg ic.jpg hc.jpg hd.jpg
fe.jpg ff.jpg fg.jpg fh.jpg

Fixation du téléviseur sur le support rotatif :

Démontage de la télé et assemblage fixation au cadre métallique à l'aide de longues vis… bien vu !
Nous voilà avec un écran réglable en profondeur.
aa.jpg bc.jpg ck.jpg
ca.jpg cn.jpg co.jpg
db.jpg da.jpg dc.jpg

Intégration de l'ensemble dans la borne :

La position de l'écran est bloquée avec une vis qui traverse la roue de vélo.
il.jpg im.jpg
ik.jpg ii.jpg ij.jpg
in.jpg io.jpg ip.jpg iq.jpg
ir.jpg is.jpg iu.jpg jj.jpg

La rotation s'effectue vers la gauche, c'est à dire dans le sens inverse des aiguilles d'une montre, ce qui est le BON sens (la majorité des jeux verticaux sur PCB sont orientés ainsi).
Pour ma part, vu que je me suis planté sur ma borne, qui tourne à droite, impossible de jouer à Ikaruga sur Game Cube ! L'image se retrouvant à l'envers…
la.jpg ld.jpg lf.jpg
lc.jpg le.jpg

Jeudi, juillet 24 2014

Un guidon de fixie en bois - DIY

Bonjour à tous.
Il y a un petit moment que je veux me faire un fixie, vous savez ces vélos "urbains", hyper dépouillés, allégés avec un pignon fixe (d'où leur nom). L'avantage du fixie: c'est beau et c'est simple (mais c'est cher...). Donc je veux en faire un moi-même avec le maximum de récup.
Aujourd'hui, je vais vous présenter le guidon. Je me suis inspiré des nouvelles tendances. Le bois revient souvent et c'est normal puisque c'est sobre et élégant.

Voici le résultat:



Petit tuto pour la réalisation:

Coté matos, il m'a fallut une scie, une perceuse, une raboteuse, une ponceuse, du papier de verre, une défonceuse, des pinceaux et du vernis.
Coté matériau: un tasseau de hêtre, du contreplaqué 10mm, une barre d'acier et une tige d'acier.

Voici les étapes de la réalisation:

Présentation des matériaux (la barre alu ne m'a pas servi pour ce cintre, mais certainement pour un prochain...):


 Découpe du bois:



Création d'une gorge à la défonceuse dans le tasseau central:



Collage de la barre d'acier + rebouchage des petits trous à la pâte à bois:


Pose de la colle (certainement l'étape la plus importante, au pinceau et s'assurer qu'il y en a bien partout):


Un peu d'aide de ma fille:


Serrage (très important aussi...)


Un jour plus tard on desserre:


Perçage des trous (pendant qu'il y a encore des faces plates)


Passage à la raboteuse:


ça commence à être propre:


Mise en place et collage des goupilles (coupées dans la barre d'acier) :


Ponçage à la ponceuse puis à la main:


ça commence à être très beau:


Vernissage et pose (en attendant d'avoir le fixie, sur un vieux VTT pour l'essai):




Le résultat est vraiment sympa et surtout très solide.


Je songe en fabriquer d'autres et les commercialiser. Mais seulement avec des modèles uniques (essences de bois, longueur et formes différentes)
Donnez moi votre avis!
A+




Wooden bike Handlerbars Homemade Lamellé-collé plywood bike diy glued-laminated bars Singlespeed

Mercredi, juillet 23 2014

OpenScad : Sega Aero City

Voici ma première modélisation 3D avec OpenScad.
Il s'agit de la borne d'arcade Japonaise « Aero City de Sega » à l'échelle 1/10, basée sur ce papercraft.

Vous la retrouverez partagée sur thingiverse : http://www.thingiverse.com/thing:398356

Elle peut s'imprimer d'un bloc avec la fonction « support » de votre logiciel d'impression, sinon à vous d'éditer le modèle 3D source pour séparer les blocs existants. Toutefois ce premier essai imprimé de taille réduite, montre des problèmes potentiels avec l'impression de l'écran, c'est pourquoi je fourni aussi deux STL avec l'écran séparé.

Cette modélisation mérite sans doute d'être améliorée, donc n'hésitez pas à modifier le fichier source .SCAD.

img_20140717_174314.jpg img_20140717_174821.jpg img_20140717_180416.jpg img_20140717_180426.jpg
img_20140717_180438.jpg img_20140717_180523.jpg img_20140717_180542.jpg img_20140717_180555.jpg

Pour compléter la scène, il faudrait modéliser un petit tabouret ^_^

Lundi, juillet 7 2014

Table de placement manuel : Le cadre

Suite à l'introduction de ma table de placement manuel, je vais poursuivre en vous présentant le cadre.

Tous le design des pièces est réalisé à l'aide de OpenSCAD et est disponible sur le dépôt GitHub suivant : GitHub / hugokernel / ManualPickAndPlace

La base

Le cadre qui va supporter la mécanique doit être suffisamment rigide pour ne pas bouger, je désire aussi quelque chose de suffisamment fin, les profilés aluminium couramment utilisé dans le milieu maker m'ont semblé parfaitement adapté.

Voici le cadre en profilé aluminium de 20mm, les profilés sont maintenus entre eux par des équerres internes :

frame.png

Concernant la taille du cadre (60x40cm), il est parfaitement possible d'avoir d'autres dimensions (tout est paramétrable dans les sources OpenSCAD), j'ai choisi cette dernière en fonction des arbres de précisions (trempés et rectifiés) de 12mm de diamètre que j'ai pu trouver.

Par dessus, nous rajoutons les supports d'arbre de précisions (réalisé via une imprimante 3D) :

rod_support.png

Les supports viennent se fixer aux 4 coins du cadre, les arbres de précision rentrent dedans en force et n'en bouge plus :

frame2.png

Pour cet étape, il faut imprimer :

Le chariot X

Les chariots pour l'axe X sont eux aussi aussi fabriqués via une imprimante 3D, ils ont chacun 2 parties creuses dans laquelle on insère des roulements linéaires (type LM12UU) dans lesquels viendront coulisser les arbres de précision.

lm12uu.png dolly_x.png

Tout ceci monté :

frame3.png

Pour cet étape, il faut imprimer :

Le chariot Y

Le chariot de l'axe Y possède 4 roulements linéaires, un support porte-outils (indiqué par la flèche) et des trous de fixation pour le "repose bras".

dolly_y_top.png dolly_y_bottom.png

frame4.png

Pour cet étape, il faut imprimer :

Récapitulatif des pièces à imprimer

Concernant l'impression des pièces, les jeux étant assez faibles, n'hésitez pas à faire quelques tests avant de tout imprimer.

Toutes les sources des pièces de cet article sont sur GitHub dans le fichier ManualPickAndPlace / cad / table.scad.

anim.gif

Ça nous donne quelque chose comme ça :

À suivre...

Dimanche, juillet 6 2014

WebRadioRéveilWifi -1-

Depuis le temps que l'idée circule d'une hémisphère à l'autre de mon cerveau dérangé, j'ai eu l'occasion de jouer un peu avec le raspi, et de faire quelques tests…

  • Essentiellement ce qui touche à la gestion des GPIO, de l'allumage de led en bash, en C et en python, aux boutons déclencheurs d'événements.

D'abord sur plaque labo, il me fallait envisager un câblage en dur pour faire des choses plus sérieuses et ainsi m'affranchir des faux contacts et autres problèmes de rebond.

  • Sur une carte à trous, j'ai donc câblé 7 boutons de récup et un connecteur HE10 pour la relier au port GPIO du raspi.

Chaque bouton a donc sa résistance de pull-up de 10kΩ, et j'ai dû y adjoindre par la suite un condensateur de 100nF anti-rebond, car force est de constater que l'anti-rebond logiciel, bah c'est de la merde. (bouncetime=xxx ms)
Du coup la place n'étant pas prévue, il sont soudés à l'arrache… bah tant-pi.
dsc09789.jpg dsc09783.jpg
dsc09786.jpg dsc09788.jpg

Ajouté également un petit connecteur jack pour récupérer le 5V du Raspberry et alimenter un ampli audio mono à base de LM386, celui-là même que j'avais fabriqué en cours de techno[1] au collège.

  • Avec ceci et un script python je suis donc à même de déclencher une playliste contenant des adresses URL de webradio, chaque boutons ayant sa propre fonction.

L'inconvénient c'est que je prévoie pas mal de fonctions et qu'il n'y aura pas suffisamment de boutons… On pourrait donc être tenté de rajouter des GPIO au Raspberry Pi en utilisant une puce MCP23017 ou 23008, mais ça ferait trop de boutons sur un radio-réveil qu'on doit pouvoir manipuler dans la pénombre.

 Voici un exemple pour deux boutons :

#!/usr/bin/env python2.7
# coding: utf-8
import time    # import des modules nécessaires
import os, sys
import RPi.GPIO as GPIO
 
CHANNEL = 17    # Définition de variables utiles
CHANNEL2 = 18
long_press = 1
very_long_press = 3
 
GPIO.setmode(GPIO.BCM)    # initialisation des GPIO
GPIO.setup(CHANNEL, GPIO.IN)
GPIO.setup(CHANNEL2, GPIO.IN)
 
def bouton17(a):    # Fonction pour GPIO 17
    button_press_timer = 0
    GPIO.remove_event_detect(CHANNEL)    # empêche le bouton d'être détecté x fois de plus
    while True:
        if(GPIO.input(a) == GPIO.LOW ):    # bouton appuyé
            button_press_timer += 0.2    # incrémente tant que le bouton est maintenu
            print button_press_timer
            print a
 
        else:    # bouton relaché
            if (button_press_timer > very_long_press):    # comparaison des durées
                print"very long press : ", button_press_timer
            elif (button_press_timer > long_press):
                print"long press : ", button_press_timer
            elif (button_press_timer > 0):
                print"short press : ", button_press_timer
            button_press_timer = 0
        time.sleep(0.2)
 
def bouton18(b):    # Fonction pour GPIO 18
    button_press_timer = 0
    GPIO.remove_event_detect(CHANNEL2) # empêche le bouton d'être détecté x fois de plus
    while True:
        if(GPIO.input(b) == GPIO.LOW ): # bouton appuyé
            button_press_timer += 0.2 # incrémente tant que le bouton est maintenu
            print button_press_timer
            print b
 
        else:    # bouton relaché
            if (button_press_timer > very_long_press):    # comparaison des durées
                print"very long press : ", button_press_timer
            elif (button_press_timer > long_press):
                print"long press : ", button_press_timer
            elif (button_press_timer > 0):
                print"short press : ", button_press_timer
            button_press_timer = 0
        time.sleep(0.2)
 
# Définition du déclenchement des boutons à la détection du front descendant
GPIO.add_event_detect(CHANNEL, GPIO.FALLING, callback=bouton17, bouncetime=100)
GPIO.add_event_detect(CHANNEL2, GPIO.FALLING, callback=bouton18, bouncetime=100)
 
while True:
 
    time.sleep (2)
GPIO.cleanup()    # Réinitialisation des GPIO en sortie de script

À charge donc de remplacer les print par les commandes désirées.
Voir aussi la doc de la librairie RPi.GPIO

À suivre…

Note

[1] EMT : Éducation Manuelle et Technologique, années 90

Jeudi, juillet 3 2014

Adaptateur Kenwood Major / Moulinex Fresh Express

Aujourd’hui l'imprimante 3D est utile à la cuisine!

DSC_3339.jpg

Après achat d'un magnifique robot Kenwood Major je pensais que l'accessoire "Metal Roto Food Cutter AT643" replacerait sans problème le "Moulinex Fresh Express" que j'utilise beaucoup mais j'ai été déçu par cet accessoire: la râpe est soit trop fine, soit trop grosse, il ne passe pas au lave-vaisselle, prend beaucoup de place, etc.

DSC_3320.jpg

Quand je l'ai acheté le "Roto Food Cutter" était beau et brillant mais je l'ai mis au lave-vaisselle (avant de l'utiliser) et il est ressorti tout terne et moche. Ce n'est qu'ensuite que j'ai regardé le manuel et effectivement il est dit qu'il ne faut surtout pas le mettre au lave-vaisselle...

Bref, il ne replace pas vraiment mon vieux "Moulinex Fresh Express" et je ne peut pas avoir les deux sur le plan de travail donc il fallait une solution: Imprimer un adaptateur pour permettre de monter les accessoire Moulinex Fresh Express sur le robot Kenwood Major... voilà qui est fait!

DSC_3330.jpg

Le coup de chance est que les deux tournent dans le même sens donc pas besoin de mécanique compliqué, juste un arbre pour faire la transmission depuis la sortie lente du robot Kenwood Major. Et voilà le résultat:

DSC_3296.jpg

DSC_3298.jpg

DSC_3341.jpg

Testé avec succès pour la préparation du repas de ce soir.

La pièce est "open-source" et dispo sur Thingiverse pour ceux qui voudrait la télécharger et l'imprimer :-)

Mardi, juillet 1 2014

Table de placement manuel : Introduction

Le projet OpenAlarm utilisera comme module de transmission des FunkyV3, des cartes de très petites tailles avec tout un tas de composants permettant la connexion à différents type de capteurs, la liaison radio avec la base, etc...

Les Funky V3 sont très petit, pourtant, ils embarquent un bon nombre de composants et pour faire tenir autant de monde sur une surface aussi réduite, pas de mystère, il faut utiliser des composants TRÈS petit, lorsque je dis très petit, je parle de la résistance au format 0402 tout à gauche de la photo ci-dessous :

comparatif_cms.png

Et j'en viens à parler d'une des choses qui fait que OpenAlarm à pris beaucoup de retard, c'est que pour pouvoir manipuler des composants aussi petit en quantité (je ne vais pas faire des cartes que pour moi), il faut du matériel approprié.

Impossible de manipuler de tels composants directement avec les mains, avec des brucelles, c'est faisable mais pas pratique, le plus adapté est d'utiliser une pompe de préhension qui n'est rien d'autre qu'une micro ventouse et si on y ajoute une table de placement, alors, là, on tend vers le parfait...

Mais c'est quoi une table de placement ?

C'est assez simple : on place la ou les cartes électroniques sur une surface, on dispose les composants à proximité, et à l'aide d'un support coulissant et par des mouvements de translation, on vient prendre les composants et on les dépose sur le pcb.

Les composants sont « pris » par un système de pompe à dépression pour une grande précision de positionnement et surtout permettant de prendre des composants dans de très petits formats.

Que trouve-t-on sur Internet ?

Un modèle commercial : ERMES - Table de positionnement CMS

Chez Selectronic, on peut trouver la table ci-dessous :

selectronic_table.png selectronic_table_2.png

Je vois plusieurs points noirs à leur système :

  • La surface sur laquelle on pose son bras est trop petite et non souple, ça sent les douleurs musculaires au bout de quelques heures d'utilisation
  • Le stylo n'est pas maintenu droit par un quelconque mécanisme, je pense qu'il est difficile de manipuler des composants très petit comme des 0402
  • Le prix n'est pas sérieux...

Le modèle en bois peu chère de vpapanik

Ce modèle est intéressant car il utilise principalement des matériaux de récupération...

low_budget_vpapanik.jpg
Photo originale de http://vpapanik.blogspot.fr/2012/11/low-budget-manual-pick-place.html

Un point intéressant est que la pointe de préhension est solidaire du support coulissant, garantissant ainsi une pose plane du composant.

Au final, le système est ingénieux mais prend beaucoup de place (en hauteur) et j'ai un léger doute concernant la stabilité de l'ensemble, enfin, le support pour le bras n'est pas adapté et à la longue, le frottement de ce dernier sur le bord à angle droit du bois ne doit pas être agréable (voir la dernière photo de son article).

La table de Brian Dorey

Alors là, ça commence à devenir du lourd :

pnp-machine_briandorey.jpg

Elle est entièrement en aluminium, elle dispose d'un vrai support pour le bras en cuir / simili, sa tête est articulée et muni d'un moteur pas à pas permettant de choisir l'orientation du composant à l'aide de bouton poussoir se trouvant sur la flanc de la machine.

Il a même publié tous les plans de sa machine sur GitHub.

C'est du super boulot, par contre, elle est difficile d'accès à cause de ses pièces usinées et je la trouve encore assez imposante...

Brian Dorey, non content de sa table de placement manuel, à enchaîné par la suite sur une table de placement automatique plutôt impressionnante : http://www.briandorey.com/?tag=/manual+pick+and+place.

Autre machines...

Je ne vais pas toutes les passer en revue, il y en a trop mais voici quelques pointeurs :

Faisons un mix de tout ça

Prenons les bonnes idées, apprenons des erreurs et créons la notre :

  • Je veux une table qui reste avec un faible encombrement en hauteur
  • Avec le maximum de pièces imprimables à l'aide d'une imprimante 3D
  • Le système d'aspiration doit être automatique, pas besoin de pédale ou de bouton supplémentaire en utilisation normale (avec tout de même un mode manuel)
  • Un support pour bras suffisamment confortable pour travailler quelques heures de suite
  • Un voyant indiquant si la pointe aspire ou non
  • Une mécanique fluide (roulements linéaires)

Au moment ou j'écris ces lignes, ma table maison est terminée et parfaitement fonctionnelle, je fais donc durer le suspens et tâcherai de pondre des articles quand je le pourrai pour décrire la machine...

- page 1 de 66