Archives de janvier, 2014

[Tutorial] Réparer sa TV Samsung

Publié: 15 janvier 2014 dans Non classé

Bonjour à tous amis bricoleurs 🙂

Alors un court article pour raconter une mésaventure qui n’a pas durer bien longtemps.

Alors il y a très longtemps mon frère m’avait parler de ce problème, et dès que ma TV s’est mise à déconner, ni une ni deux je n’ai pas hésiter. Le problème est assez connu, on trouve pas mal d’info sur le net, autant faut-il déjà en avoir eu vent.

Les symptômes : votre TV ne s’allume plus ou a du mal (mon cas) , l’écran scintille … Bref en réalité pour une même cause les conséquences peuvent prendre bien des formes.

La cause : des condensateurs au niveau de l’étage d’alimentation rendent l’âme. Et une alimentation qui pare en vrille peut avoir des répercutions sur n’importe lequel des sous-systèmes qu’elle alimente, d’où la variété de problèmes constatés.

Donc hop je démonte et bingo :

WP_20140113_002

WP_20140113_003

WP_20140113_010

On voit assez nettement que 3 condos on fait de la « gonflette », signe typique de leur décès. A la rubrique nécrologique on trouve donc  trois 820 µF 25V.

Quel condensateur prendre pour le remplacement ?

Alors tant qu’à faire on va pas refaire la même erreur que le fabricant : si ces condensateurs rendent l’âme c’est qu’ils ont été mal dimensionnés. Donc plutôt que des 25V j’ai mis des 35V et 40V (j’ai fait de la récup). La règle absolu dans tous les cas c’est de prendre un voltage au moins équivalent. Mettez en un plus faible et votre condensateur va très certainement exploser ! Après pour la capacité il faut prendre idéalement la même, perso je n’en avais pas donc j’ai mis des 470µF pour deux des trois (le troisième a eu droit au 820 µF) et ça marche très bien. Et dernier point, bien évidemment faîtes attention à la taille du condensateur qu’elle soit à la fois compatible par rapport aux autres composants, et également qu’il ne soit pas trop grand auquel cas vous ne pourriez  plus remonter le panneau arrière de votre TV …

La réparation est donc enfantine : on démonte le panneau derrière la TV, on débranche les quelques nappes, on dévisse la fameuse carte, on joue du fer à souder pour changer les condos et on reprend les étapes en sens inverse.

Note importante : faîtes bien évidemment attention aux polarités des condensateurs ! Inversion = explosion directe

Une fois réparé :

WP_20140114_011

Pourquoi foutre des condensateurs sous/mal dimensionnés ?

Et oué on est quand en droit de se dire qu’ils abusent chez Samsung, c’est quand même leur boulot ! Pour moi trois explications possibles et cumulables :

– Obsolescence programmée : c’est à la mode, fini les produits qui durent 20 ans. Société de consommation quand tu nous tiens … Et insérer volontairement des « points faibles » dans les appareils qui lâchent quelques temps après la garantie c’est devenu malheureusement monnaie courante …

– Limiter les coûts : plus la capacité ou le voltage est élevé, plus le condensateur coûte cher. Vous allez me dire « pour 20 centimes ?! Sérieusement ?? » Et oui, 20 centimes multiplié par des centaines de milliers de produits (en plus que ça permet de limiter le nombre de composants utilisés et donc d’en commander plus à la fois et donc de réduire encore plus le prix à l’unité) ça commence à faire des sommes non négligeables (faut bien payer les amendes à Apple :p )

– Les spécifications des fabricants de condensateur se réduisent de plus en plus. En effet alors qu’avant un fabricant donnait son condo à 25V, il pouvait en réalité en supporter plus. Maintenant on est vraiment proche des 25V …

Bref vous le saurez si ça vous arrive : inutile de jeter votre TV à la benne !

Quelques liens utiles :

http://www.conseil-creation.com/electronique/tv_samsung_panne_alimentation.php

http://tendactu.fr/votre-tv-samsung-en-panne-normal-cetait-prevu/867/

http://forum.ubuntu-fr.org/viewtopic.php?id=736861

Publicités

Bonjour à tous,

Pour commencer : non je ne suis pas mort mais très occupé 🙂

Je bosse sur pas mal de sujet, y’en a un qui devrait vous intéresser et que je vous présenterai à la fin du mois si tout va bien (en attente des PCB de Chine). Pour l’instant suspens :p

Alors qu’est-ce qui nous amène aujourd’hui : n’avait vous jamais rêvé d’une lumière qui s’allume et s’éteint en tapant dans vos mains ? Et bien ce doux rêve est à portée de bras 🙂

Matériel

– Une arduino (ici j’ai pris une pro mini) + 1 bouton

WP_20140114_001

– Au besoin comme moi, un convertisseur USB <-> Serie :

WP_20140114_005

– Un module chinois de détection sonore :

WP_20140114_004

– Un module  relais chinois :

WP_20140114_003

– Des bras et un cerveau.

Bon vous l’aurez noter peut-être, mis à part les bras et le cerveau tout est en provenance direct de Hongkong, histoire de tester ces modules au passage 😉

Montage

Rien de complexe du tout. Pour le module sonore : deux pins pour l’alimentation, et un pin OUT à brancher sur une entrée digitale de l’Arduino. Ce pin est HIGH lorsqu’il n’y a aucun son et passe à LOW lorsqu’il en détecte un, le seuil se réglant avec le petit potentiomètre dessus. Une LED permet de visualiser la détection.

Pour le module relais rien de fantastique non plus : deux fils pour l’alim et un pour la commande. Ici attention, suivant les modules, le relais ne s’active pas sur le même état. Sur le mien justement HIGH = relais ouvert et LOW = relais fermé

Le bouton la c’est du classico-clasique : une borne au GND, l’autre à un pin digital configuré en INPUT_PULLUP.

Enfin si comme moi vous avez une pro mini, il vous faut raccorder le convertisseur USB<->Série : RX à TX, TX à RX, DTR à DTR, GND à GND et au besoin 5V à VCC.

Programmation

La ça se corse … En fait le codage ne fait pas appel à des notions complexes, mais ça demande une certaine gymnastique mentale pour transcrire le problème réel en code. Le principe de base et le suivant :

Quand je tape dans mes mains, un signal est détecté par l’Arduino. millis() est alors mis en mémoire (si vous êtes déjà perdu cet article devrait vous aider), c’est le point de départ.  Lorsque je retape, l’Arduino détecte le signal et fait la différence entre millis() et le point de départ précédemment enregistré. Cet écart est mis en mémoire dans un tableau. On remet à zéro le point de départ et on recommence. On se retrouve ainsi avec un tableau rempli d’écart entre deux frappes : ça y est, on a sauvegarder notre rythme !

Comme un schéma vaut parfois mieux qu’un long discours :

WP_20140114_010

Alors ça c’est pour le principe de base. Maintenant on veut également ne pas avoir a enregistrer la rythmique à chaque démarrage, donc on va faire appel à l’EEPROM. Pour ceux qui l’ignore, l’EEPROM est une mémoire morte. On en retrouve dans la quasi totalité des microcontrôleurs. Alors qu’est-ce qu’elle a de spécial cette mémoire ? Et bien c’est assez simple : on va pouvoir y stocker des variables et pour toujours (en tout cas, tant qu’on ne réécrit pas dessus) et ce, en passant par un programme ! Typiquement, cette mémoire sert à stocker des variables de configuration amenées à être modifiées durant la vie du système, par exemple le contraste d’un écran : on va pas s’amuser à chaque démarrage à aller dans les menus pour remettre un contraste qui nous semble correct. On stocke en mémoire ce contraste et au redémarrage on recharge cette variable. Dans le montage qui nous intéresse ici, on va donc se servir de cette mémoire pour enregistrer notre rythmique. Attention cependant, le point faible de cette mémoire est qu’elle a un nombre d’écriture limité : 100 000 écritures d’après la datasheet. En réalité c’est une durée de vie minimum, mais si ça se trouve elle peut durer 10 fois plus. En tout cas ce qu’il faut retenir c’est que ce n’est pas une mémoire où il faut écrire régulièrement, sinon on la flingue assez vite. A noter qu’en revanche il n’y a aucune limite en lecture.

Il y aura donc deux modes de fonctionnement : un mode écoute (le fonctionnement « normal » quoi) et un mode enregistrement, qui sera déclenché par l’appui sur le bouton.

Alors on va commencer par l’enregistrement car ça me semble plus facile pour comprendre l’écoute ensuite.

Brute de fonderie, le code :

void Enregistrement(){

Blink(); // fonction qui fait clignoter la LED signifiant le passage en mode enregistrement
 Depart=millis(); // la sortie de Blink() se fait sur la détection du premier clap, donc on prend le point de départ

Stab();

int j=0;

while(millis()-Depart<TIMEOUT && i<50){ // on boucle tant que le timeout n'est pas dépassé on qu'on enregistre pas plus que ce qu'on peut

if(digitalRead(INMIC)==LOW){ // son détecté

Sequence[j++]=millis()-Depart; // on enregistre le temps écoulé
 Depart=millis(); // remise à zéro du point de départ

Stab();

}

}

NombreDeClap=j+1;

SauvegardeEEPROM();

Play();

Mode=ECOUTE;

}

Alors avant toute chose, vous noterez les appels à certaines fonctions. Ne vous inquiétez pas on va les voir. Donc on commence par la fonction Blink() :

void Blink() {

Depart=millis();

byte State_LED=HIGH;

while(digitalRead(INMIC)==HIGH) {

digitalWrite(LED,State_LED);

if(millis()>=(Depart+500)) {
 Depart=millis();
 State_LED = !State_LED;
 }

}

digitalWrite(LED,LOW);

}

Son principe est simple : faire clignoter la LED mais de manière non bloquante : dès qu’il y a un signal sonore, hop on sort. Si vous êtes perdu je vous renvoi vers le même article.

Ensuite on tombe sur Stab(). Vous allez me dire que faire une fonction pour 2 lignes c’est pas forcement utile. Oui mais on y fait appel plusieurs fois dans le programme, donc bon …

void Stab(){

while(digitalRead(INMIC)==LOW); // tant que le détecteur n'est pas revenu à l'état normal on boucle
 delay(REBOND); // anti-rebond

}

Sa fonction est simple : un signal sonore n’est jamais un pic parfait ce qui fait que le signal dure plusieurs millisecondes, donc si on ne veut pas avoir de problème, il faut attendre que le signal « retombe ». Pour ce faire on se mets dans une boucle while() tant que le signal est LOW (=son détecté) et en plus derrière on place en plus un delay() par sécurité (on attend que les choses « se tassent » 😉 ). REBOND est défini en en-tête, on le verra plus tard.

Donc la ça y est le top départ est donné : Depart = millis() ==> mis en mémoire du « Top depart » du chrono.

On rentre alors dans une boucle while() dont on ne sortira qu’à deux conditions : si on dépasse un certain temps (timeout) ou si on arrive à la limite de notre tableau Sequence[] qui permet de sauvegarder notre rythmique.

Alors dès qu’un signal est détecté, on mesure le temps écoulé par rapport au premier « clap », on remet à zéro Depart, on attend le retour à la normale du capteur (Stab()), et on repart pour un tour. Dès qu’on sort de la boucle (trop de clap ou bien on a arrêté de taper et on a dépassé le timeout) on lance la sauvegarde en EEPROM :

void SauvegardeEEPROM(){

EEPROM.write(0,NombreDeClap); // adresse zéro on stocke le nombre de clap

int y=1;

for(i=0;i<NombreDeClap-1;i++) {

EEPROM.writeLong(y+=4,Sequence[i]); // long = 4 bytes

}

}

Alors ici si vous n’avez jamais jouer avec l’EEPROM forcément ça risque de vous parlez un peu chinois (en même temps vu d’où viennent les modules xD)

L’EEPROM est diviser en byte, soit 8 bits. Chaque byte porte une adresse. Pour un atmega 328 qui a 1024byte de mémoire, les adresses vont donc de 0 à 1023. Mais comme ce sont des bytes, on ne peut stocker de base que des nombre entre 0 et 255. Donc pour stocker un « long » qui fait 4 bytes, il faudra donc utiliser les adresses en 4 par 4. Alors écrire une routine pour le faire n’est pas compliqué, mais il y a une librairie qui le fait directement, elle s’appelle EEPROMex.h

Donc je m’en sers ici mais il faut quand même tenir compte du fait qu’elle ne prend pas en compte le type de variable écrit par rapport à l’adresse (je sais c’est pas clair). Par exemple : si j’utilise EEPROM.writeLong(0,MaVariable1) puis  EEPROM.writeLong(1,MaVariable2), je vais écraser 3 blocs sur 4 de MaVariable1 ! Il faut écrire   EEPROM.writeLong(4,MaVariable2). Ainsi aux byte d’adresse 0, 1,2 et 3 j’aurai stocké  MaVariable1 et à ceux dont l’adresse est 4,5,6 et 7 MaVariable2.

Pour en revenir à nos moutons, il me suffit donc de faire une simple boucle for pour recopier les différents index de Sequence[] dans l’EEPROM. Sequence[0] à l’adresse 1, Sequence[1] à l’adresse 5, Sequence[2] à l’adresse 9 etc …

Au chargement du programme on fera donc simplement la manip inverse :

void ChargementEEPROM(){

if(EEPROM.read(0)<=50){

NombreDeClap=EEPROM.read(0);

int w=1;

for(int e=0;e<NombreDeClap-1;e++) {
 Sequence[e]=EEPROM.readLong(w+=4);
 }

}
 else {
 Mode=ENREGISTREMENT; // si nombre de clap invalide on passe en mode enregistrement
 }
 }

Une fois la sauvegarde effectuée on passe à Play() qui va jouer l’enregistrement qu’on vient de record, et ce, sur la LED 13 de la carte :

void Play() {

Pulse();

for(int u=0;u<NombreDeClap-1;u++){

delay(Sequence[u]);

Pulse();

}

Serial.println("");

}

void Pulse(){

digitalWrite(LED,HIGH);
 delay(50);
 digitalWrite(LED,LOW);

}

Donc la je pense que si vous avez compris le principe de base, vous comprendrez ce passage de vous même.

Maintenant passons à la partie un peu plus velue (et oui ça c’était la partie facile, en tout cas pour moi je trouve ça bien plus facile à appréhender que l’écoute) :

void Ecoute(){

if(digitalRead(INMIC)==LOW){ // son détecté ?

Time = millis()-Depart; // Temps écoulé depuis le précédent clap
 Ecart = float(Sequence[i])-float(Time); // Ecart entre le temps "attendu" et celui réalisé

if(abs(Ecart) <=TIME_ERROR){ // si l'écart constaté est dans l'erreur tolérée

i++; // le compteur de "bonne réponse" est incrémenté

Depart=millis(); // RAZ du chrono

if(i>=NombreDeClap-1){ // si le nombre de bonne réponse est atteint

State= !State; // si le relais était allumé on l'éteint et vice-versa
 digitalWrite(RELAY,State);
 New(); // on repart à zéro

}

} else { // si mauvaise réponse

New(); // on repart à zéro

}

Stab();

}
 }

void New(){

Depart=millis();
 i=0;

}

La je pense avoir commenté au maximum le code, si jamais vous ne pigez pas y’a les commentaires 😉

Bon si maintenant on rassemble tout, qu’on rajoute la prise en charge de la liaison série, le setup() et tout, ça nous donne :

#include <EEPROMex.h>
 #include <EEPROMVar.h>

//configuration des pins
 #define INMIC 2 // entrée détecteur de son
 #define RELAY 5
 #define BOUTON 10
 #define LED 13

// constantes pour rendre le code plus lisible
 #define ECOUTE 4
 #define ENREGISTREMENT 5

//constantes de réglage
 #define TIMEOUT 3000
 #define TIME_ERROR 200
 #define REBOND 100

unsigned long Sequence[50]={0}; // sers à stocker l'air
 unsigned long Depart,Time;
 float Ecart;
 int NombreDeClap,i;
 byte Mode,State; // Mode permet de définir le comportement et State est la variable de commande du relais
 char buffer [100]; // Tampon pour les sprintf
 void setup(){

Serial.begin(9600);

// Configuration des variables

Mode=ECOUTE; // par défaut on écoute
 State=HIGH; // sur mon module relais, à LOW le relais est fermé et inversement
 i=0;

// Configuration des pins

pinMode(BOUTON,INPUT_PULLUP);
 pinMode(INMIC,INPUT);
 pinMode(RELAY,OUTPUT);

digitalWrite(RELAY,State);

ChargementEEPROM(); // Chargement de Sequence[]

Play(); // la séquence est jouée sur la LED 13
 }

void loop() {

// si appui bouton, on passe en mode enregistrement
 if(digitalRead(BOUTON)==LOW) {
 Mode=ENREGISTREMENT;
 while(digitalRead(BOUTON)==LOW); // tant que le bouton est appuyé on boucle
 delay(50); //anti-rebond
 }

switch(Mode) {

case ECOUTE:

Ecoute();

break;

case ENREGISTREMENT :

Enregistrement();

break;

}

}

void Ecoute(){

if(digitalRead(INMIC)==LOW){

Time = millis()-Depart; // Temps écoulé depuis le précédent clap
 Ecart = float(Sequence[i])-float(Time); // Ecart entre le temps "attendu" et celui réalisé

if(abs(Ecart) <=TIME_ERROR){ // si l'écart constaté est dans l'erreur tolérée

Serial.println("OK");

i++; // le compteur de "bonne réponse" est incrémenté

Depart=millis(); // RAZ du chrono
 Serial.println(i);

if(i>=NombreDeClap-1){ // si le nombre de bonne réponse est atteint

Serial.println("Sequence validee");
 State= !State; // si le relais était allumé on l'éteint et vice-versa
 digitalWrite(RELAY,State);
 New(); // on repart à zéro

}

} else { // si mauvaise réponse

sprintf (buffer, "Realise = %d ms Attendu = %d ms Ecart = %d ms ", Time, Sequence[i], Ecart);
 Serial.println(buffer);
 Serial.println(Ecart<0?"Pas OK Trop lent":"Pas OK Trop rapide"); // <=> if(Ecart<O) Serial.println("Trop lent"); else Serial.println("Trop rapide");

New(); // on repart à zéro

}

Stab();

}
 }

void Enregistrement(){

Serial.println("Enregistrement");

Blink(); // fonction qui fait clignoter la LED signifiant le passage en mode enregistrement
 Depart=millis(); // la sortie de Blink() se fait sur la détection du premier clap, donc on prend le point de départ

Serial.println("Debut enregistrement");

Stab();
 int j=0;

while(millis()-Depart<TIMEOUT && i<50){ // on boucle tant que le timeout n'est pas dépassé on qu'on enregistre pas plus que ce qu'on peut

if(digitalRead(INMIC)==LOW){ // son détecté

Sequence[j++]=millis()-Depart; // on enregistre le temps écoulé
 Depart=millis(); // remise à zéro du point de départ

Stab();

}

}

Serial.println("Fin enregistrement");

NombreDeClap=j+1;

SauvegardeEEPROM();
 Play();

Mode=ECOUTE;

}

void New(){

Serial.println("New");
 Depart=millis();
 i=0;

}

void ChargementEEPROM(){

if(EEPROM.read(0)<=50){

NombreDeClap=EEPROM.read(0);

Serial.print(NombreDeClap);
 Serial.println(" claps ");

int w=1;

for(int e=0;e<NombreDeClap-1;e++) {
 Sequence[e]=EEPROM.readLong(w+=4);
 sprintf(buffer,"Adresse %d Sequence[%d] = %d",w-4,e,Sequence[e]);
 Serial.println(buffer);
 }

}
 else {
 Serial.println("Le chargement a echoue");
 Mode=ENREGISTREMENT;
 }
 }

void SauvegardeEEPROM(){

Serial.println("Sauvegarde EEPROM");

EEPROM.write(0,NombreDeClap);

Serial.print(NombreDeClap);
 Serial.println(" claps ");

int y=1;

for(i=0;i<NombreDeClap-1;i++) {

EEPROM.writeLong(y+=4,Sequence[i]);
 sprintf(buffer,"Adresse %d Sequence[%d] = %d",y-4,i,Sequence[i]);
 Serial.println(buffer);

}

}

void Stab(){

while(digitalRead(INMIC)==LOW); // tant que le détecteur n'est pas revenu à l'état normal on boucle
 delay(REBOND); // anti-rebond

}

void Play() {

Pulse();

for(int u=0;u<NombreDeClap-1;u++){

delay(Sequence[u]);

Pulse();

Serial.print(Sequence[u]);
 Serial.print(" ");
 }

Serial.println("");

}

void Pulse(){

digitalWrite(LED,HIGH);
 delay(50);
 digitalWrite(LED,LOW);

}

void Blink() {

Depart=millis();

byte State_LED=HIGH;

while(digitalRead(INMIC)==HIGH) {

digitalWrite(LED,State_LED);

if(millis()>=(Depart+500)) {
 Depart=millis();
 State_LED = !State_LED;
 }

}

digitalWrite(LED,LOW);

}

Une fois écrit c’est sûr que ça parait facile (pour ceux qui trouve ça facile). Mais faîtes comme si vous n’aviez rien vu et partez d’une page blanche 😉

En vidéo :

Application sorti du labo

Si maintenant on installait ça pour commander la lumière du salon 🙂

Bilan : on se rend compte que le module micro est très limite. Ça marche très bien à 50 cm et au-delà ça devient assez bof. Mais bon en même temps pour 2€ fallait pas s’attendre à grand chose. Mais je n’ai pas encore dit mon dernier mot 😉

Amelioration

La clairement je ne vois qu’une seule amélioration : la partie détection sonore dont les faiblesses deviennent assez gênantes une fois qu’on applique le montage en situation réelle. Concrètement ça consisterait en quoi ? D’une part mise en place d’un filtre (passe bande surement) pour affiner la détection et limiter les perturbations, ainsi il n’y a que le « type » de son qui nous intéresse qui déclencherait un signal. Je pense que déjà la on y gagnerait beaucoup car derrière on peut mettre en place une amplification plus importante et plus fine.

Autre piste qui ne changerai pas grand chose : utiliser un capteur piezzo pour par exemple taper sur n’importe quelle partie du sol ou du mur pour allumer la lumière. La aussi un petit circuit filtre+amplificateur et ça pourrait donner quelque chose du tonnerre 😉