Forum Électro-Bidouilleur

Merci de vous connecter ou de vous inscrire.

Connexion avec identifiant, mot de passe et durée de la session
Recherche avancée  

Nouvelles:

Bienvenue au Forum de discussion Électro-Bidouilleur! Inscrivez-vous pour participer aux discussions!: 
http://forum.bidouilleur.ca/index.php?action=register Les demandes d'inscription sont révisées quotidiennement.

Voir les contributions

Cette section vous permet de consulter les contributions (messages, sujets et fichiers joints) d'un utilisateur. Vous ne pourrez voir que les contributions des zones auxquelles vous avez accès.

Messages - sylvainmahe

Pages: [1] 2 3
1
Vos projets et Montages d'Électronique / Re : Programmer sans <math.h>
« le: janvier 03, 2021, 07:06:52 pm »
Bonjour :)

Quel intérêt à réécrire une bibliothèque s'il n'y a pas de gain quelque part : place ou vitesse ?

Ok, j'aurais pu garder une autre phrase cité, mais j'ai gardé celle-ci car je trouve qu'elle est tout à fait symptomatique de l'époque dans laquelle nous vivons. L'époque des plats préparés, du tout prêt sans réfléchir, du "bah ça existe déjà en mieux donc pourquoi s'emmerder ?".

Par exemple, pourquoi construire une GT40 puisque celle-ci existe déjà en peut être plus performante que la réalisation de ce monsieur : https://www.youtube.com/watch?v=Y3qAjsiNTcE

Réponse ? Pour ma part je sais, mais d'autres ne savent certainement pas au vu de ce que je peux lire assez régulièrement sur des forums.
C'est un exemple parmis tant d'autres mais, juste que certains dans la vie ont des rêves, les réalisent, et d'autres n'en n'ont aucun, simplement et efficacement.


L'utilité de ce que je vous est proposé qui comme déjà expliqué est :
Citer
Il est important d'appréhender que les fonctions mathématiques implémentées ne sont qu'une des façons possibles d'effectuer les calculs et résoudre les fonctions énoncées, ceci dans un certain langage de programmation (le C++), et d'une manière subjective avec une approche et une résolution des problématiques tout à fait singulière et arbitraire, modeste expression partagée libre et ouverte de son auteur.

...Dans un but (j'ai oublié de préciser) de comprendre comment construire ce genre de fonction mathématique, d'apprendre, d'expérimenter, en sachant pertinemment que ce ne sont pas les plus rapides du monde, par contre elles sont certainement assez compréhensibles au niveau de leur logique ce qui peut aider pas mal de monde dans d'autres domaines.

Mais surtout et c'est important de préciser, que les microcontrôleurs (je reste dans le domaine de l'embarqué) ne disposent pas de ces fonctions sans ajout en logiciel de bibliothèques (via les directives include) faites par des personnes tierces, de sorte que personne ne devrait pouvoir faire un calcul de sinus par exemple sans l'avoir programmé en amont, mise à part ce que j'appelle les tricheurs, ou que Guy Mahé, artiste en sont temps, aurait appellé une tromperie immense certainement.


Certaines personnes sont animées par quelque chose qui les dépassent completement, personnes incomprises de la majorité des gens, mais personnes partageuses, peut être trop généreuses ? J'en fait partie, en tout cas tout ce que je sais c'est que, si je ne fais pas ça alors je meurs, si je ne suis pas encore mort c'est que je créé par moi même des choses, à partir du plus bas que je peux dans le temps impartie qui me reste encore pour le faire ! Le jour ou j'arrête ça, alors je serais dans la tombe, puisque ce n'est que la seule création qui m'anime.


Question vitesse de mes fonctions j'ai fait ce que j'ai pu en amateur pour qu'elles soient les plus rapides tout en restant bien lisibles et propres, ça ne les empêchent pas de fonctionner dans tous mes projets dont celui-ci : https://www.youtube.com/watch?v=26rtRJEKDJQ


Mais si des personnes dont papyblue ont des developpements à apporter :
Citer
Personnellement, je préfère utiliser le calcul en virgule fixe et des méthodes tabulées ou des développements limités.

Il faut les partager et les expliquer !
Sachant que la vitesse seule ne veut rien dire, il faut aussi que les fonctions aient une certaine précision (tout est possible).

Bref, tout dépend des projets, mais pour l'instant avec tout l'embarqué que j'ai fait, toutes les fonctions présentées et expliquées ici ont étés testées à de multiples reprises dans différents projets et conviennent à mes modestes applications d'amateur souhaitant simplement partager des choses avec les gens.

2
Vos projets et Montages d'Électronique / Re : Les livres de sauvegarde
« le: décembre 31, 2020, 12:11:32 pm »
N'hésitez pas si vous avez besoin de créer un livre de vos fichiers informatiques, je peux vous aider. J'en ai encore mis un en production récemment afin de sauvegarder, et de partager cela avec des amis autour d'une table sans avoir besoin de faire appel à de l'électricité et des écrans d'ordinateur :)

Je fais appel à l'imprimeur https://www.pumbo.fr/ qui est vraiment simple, rapide, et respecte vraiment bien les caractéristiques de mes fichiers PDF.

Ils demandent 2 fichiers, un pour le contenu et un pour la couverture du livre.

N'hésitez pas si vous avez des questions ;)

3
Vos projets et Montages d'Électronique / Programmer sans <math.h>
« le: décembre 31, 2020, 10:50:42 am »
Bonjour ;)

Je souhaite partager avec vous un travail amateur mais autodidacte que j'ai titré : Programmer sans <math.h>

(cette proposition s'adresse au langage C++ à destination de microcontrôleurs, mais est facilement applicable au C ou à tout autre langage de programmation)


En électronique numérique embarquée qui met en œuvre des calculateurs programmables, et plus largement en programmation générale C++ (le langage utilisé pour écrire les fonctions énoncées ici), la logique pure est généralement accompagnée de calculs arithmétiques pour mener à bien la plupart des projets. Pour se faire, les calculateurs utilisés (soit les microcontrôleurs) sont équipés chacun d'une unité arithmétique et logique, partie du circuit intégré dédiée à de telles opérations, mais ce matériel ne permet pas d'effectuer des opérations arithmétiques autres que les calculs élémentaires, soit les additions, les soustractions, les multiplications, ou les divisions :

Comprendre que des opérations plus complexes comme par exemple sinus ou cosinus (que l'on retrouve habituellement dans les calculatrices modernes), ne sont pas câblées dans ce type de circuit intégré (comme c'est le cas dans la majorité des microcontrôleurs).

En conséquence, les opérations mathématiques plus élaborées doivent être écrites manuellement lors de la programmation logicielle, ceci en utilisant un certain nombre d'instructions logiques de base (structures conditionnelles, comparaisons, décalages) et d'instructions arithmétiques simples (additions, soustractions, multiplications, et divisions), seules disponibles dans les architectures matérielles des microcontrôleurs.

Cette recherche et construction logicielle effectuée, toutes les opérations (dont les ensembles constituent les algorithmes) qui œuvrent dans le fonctionnement intime de sinus ou cosinus (pour reprendre l'exemple) peuvent pour une question pratique de lisibilité et portabilité du programme être encapsulées dans des fonctions autonomes dédiées, autrement-dit regroupées dans des blocs de code distincts contenant chacun toutes les opérations nécessaires à leur fonctionnement interne, de sorte de pouvoir à posteriori en faire usage facilement en un minimum de lignes de programmation, ceci sans avoir besoin de ressources annexes externes. C'est ce que permettent les fonctions mathématiques décrites ci-dessous.

Descriptif des fonctions mathématiques :

- floor : arrondit un nombre décimal à l'entier inférieur.
- round : arrondit un nombre décimal à l'entier le plus proche.
- ceil : arrondit un nombre décimal à l'entier supérieur.
- curve : créé des interpolations linéaires ou exponentielles de courbes.
- wurve : créé des interpolations linéaires ou exponentielles dissymétriques de courbes.
- range : cadre une valeur dans un intervalle.
- center : calcule la moyenne de deux valeurs.
- pow : calcule la puissance d'un nombre.
- sqrt : calcule la racine carrée d'un nombre.
- fact : calcule la factorielle d'un nombre.
- sin : trouve le sinus d'un angle.
- cos : trouve le cosinus d'un angle.
- tan : trouve la tangente d'un angle.
- arcsin : trouve l'angle à partir d'un sinus.
- arccos : trouve l'angle à partir d'un cosinus.
- arctan : trouve l'angle à partir d'une tangente.
- arctan2 : trouve l'angle à partir de la tangente de deux arguments x et y.

Il est important d'appréhender que les fonctions mathématiques implémentées ne sont qu'une des façons possibles d'effectuer les calculs et résoudre les fonctions énoncées, ceci dans un certain langage de programmation (le C++), et d'une manière subjective avec une approche et une résolution des problématiques tout à fait singulière et arbitraire, modeste expression partagée libre et ouverte de son auteur.





Détails des fonctions

Fonction floor :
signed long floor (const float VALUE)
{
signed long value = 0;

if (VALUE <= 0)
{
value = VALUE - 1.0;
}
else
{
value = VALUE;
}

return value;
}

Fonction round :
signed long round (const float VALUE)
{
signed long value = 0;

if (VALUE <= 0)
{
value = VALUE - 0.5;
}
else
{
value = VALUE + 0.5;
}

return value;
}

Fonction ceil :
signed long ceil (const float VALUE)
{
signed long value = 0;

if (VALUE <= 0)
{
value = VALUE;
}
else
{
value = VALUE + 1.0;
}

return value;
}

Fonction curve :
float curve (const float POSITION_START, const float POSITION_CURRENT, const float POSITION_END, const float INTERPOLATION_START, const float INTERPOLATION_END, const float CURVE)
{
float value = 0;

if ((POSITION_START < POSITION_END && POSITION_CURRENT <= POSITION_START) || (POSITION_START > POSITION_END && POSITION_CURRENT >= POSITION_START))
{
value = INTERPOLATION_START;
}
else if ((POSITION_START < POSITION_END && POSITION_CURRENT >= POSITION_END) || (POSITION_START > POSITION_END && POSITION_CURRENT <= POSITION_END))
{
value = INTERPOLATION_END;
}
else
{
if (INTERPOLATION_END > INTERPOLATION_START)
{
if (CURVE == 0)
{
value = INTERPOLATION_START + ((INTERPOLATION_END - INTERPOLATION_START) * ((POSITION_CURRENT - POSITION_START) / (POSITION_END - POSITION_START)));
}
else if (CURVE > 0)
{
value = INTERPOLATION_START + (((INTERPOLATION_END - INTERPOLATION_START) * ((POSITION_CURRENT - POSITION_START) / (POSITION_END - POSITION_START))) / ((CURVE + 1.0) - (CURVE * ((POSITION_CURRENT - POSITION_START) / (POSITION_END - POSITION_START)))));
}
else
{
value = INTERPOLATION_END - (((INTERPOLATION_END - INTERPOLATION_START) * ((POSITION_CURRENT - POSITION_END) / (POSITION_START - POSITION_END))) / (1.0 + (-CURVE * ((POSITION_CURRENT - POSITION_START) / (POSITION_END - POSITION_START)))));
}
}
else
{
if (CURVE == 0)
{
value = INTERPOLATION_START - ((INTERPOLATION_START - INTERPOLATION_END) * ((POSITION_CURRENT - POSITION_START) / (POSITION_END - POSITION_START)));
}
else if (CURVE > 0)
{
value = INTERPOLATION_START - (((INTERPOLATION_START - INTERPOLATION_END) * ((POSITION_CURRENT - POSITION_START) / (POSITION_END - POSITION_START))) / ((CURVE + 1.0) - (CURVE * ((POSITION_CURRENT - POSITION_START) / (POSITION_END - POSITION_START)))));
}
else
{
value = INTERPOLATION_END + (((INTERPOLATION_START - INTERPOLATION_END) * ((POSITION_CURRENT - POSITION_END) / (POSITION_START - POSITION_END))) / (1.0 + (-CURVE * ((POSITION_CURRENT - POSITION_START) / (POSITION_END - POSITION_START)))));
}
}
}

return value;
}

Fonction wurve :
float wurve (const float POSITION_START, const float POSITION_CURRENT, const float POSITION_END, const float INTERPOLATION_START, const float INTERPOLATION_CENTER, const float INTERPOLATION_END, const float CURVE_START, const float CURVE_END)
{
const float POSITION_CENTER = POSITION_START + ((POSITION_END - POSITION_START) / 2.0);
float value = 0;

if ((POSITION_START < POSITION_END && POSITION_CURRENT < POSITION_CENTER) || (POSITION_START > POSITION_END && POSITION_CURRENT > POSITION_CENTER))
{
if ((POSITION_START < POSITION_CENTER && POSITION_CURRENT <= POSITION_START) || (POSITION_START > POSITION_CENTER && POSITION_CURRENT >= POSITION_START))
{
value = INTERPOLATION_START;
}
else if ((POSITION_START < POSITION_CENTER && POSITION_CURRENT >= POSITION_CENTER) || (POSITION_START > POSITION_CENTER && POSITION_CURRENT <= POSITION_CENTER))
{
value = INTERPOLATION_CENTER;
}
else
{
if (INTERPOLATION_CENTER > INTERPOLATION_START)
{
if (CURVE_START == 0)
{
value = INTERPOLATION_START + ((INTERPOLATION_CENTER - INTERPOLATION_START) * ((POSITION_CURRENT - POSITION_START) / (POSITION_CENTER - POSITION_START)));
}
else if (CURVE_START > 0)
{
value = INTERPOLATION_CENTER - (((INTERPOLATION_CENTER - INTERPOLATION_START) * ((POSITION_CURRENT - POSITION_CENTER) / (POSITION_START - POSITION_CENTER))) / (1.0 + (CURVE_START * ((POSITION_CURRENT - POSITION_START) / (POSITION_CENTER - POSITION_START)))));
}
else
{
value = INTERPOLATION_START + (((INTERPOLATION_CENTER - INTERPOLATION_START) * ((POSITION_CURRENT - POSITION_START) / (POSITION_CENTER - POSITION_START))) / ((-CURVE_START + 1.0) - (-CURVE_START * ((POSITION_CURRENT - POSITION_START) / (POSITION_CENTER - POSITION_START)))));
}
}
else
{
if (CURVE_START == 0)
{
value = INTERPOLATION_START - ((INTERPOLATION_START - INTERPOLATION_CENTER) * ((POSITION_CURRENT - POSITION_START) / (POSITION_CENTER - POSITION_START)));
}
else if (CURVE_START > 0)
{
value = INTERPOLATION_CENTER + (((INTERPOLATION_START - INTERPOLATION_CENTER) * ((POSITION_CURRENT - POSITION_CENTER) / (POSITION_START - POSITION_CENTER))) / (1.0 + (CURVE_START * ((POSITION_CURRENT - POSITION_START) / (POSITION_CENTER - POSITION_START)))));
}
else
{
value = INTERPOLATION_START - (((INTERPOLATION_START - INTERPOLATION_CENTER) * ((POSITION_CURRENT - POSITION_START) / (POSITION_CENTER - POSITION_START))) / ((-CURVE_START + 1.0) - (-CURVE_START * ((POSITION_CURRENT - POSITION_START) / (POSITION_CENTER - POSITION_START)))));
}
}
}
}
else if ((POSITION_START < POSITION_END && POSITION_CURRENT > POSITION_CENTER) || (POSITION_START > POSITION_END && POSITION_CURRENT < POSITION_CENTER))
{
if ((POSITION_CENTER < POSITION_END && POSITION_CURRENT <= POSITION_CENTER) || (POSITION_CENTER > POSITION_END && POSITION_CURRENT >= POSITION_CENTER))
{
value = INTERPOLATION_CENTER;
}
else if ((POSITION_CENTER < POSITION_END && POSITION_CURRENT >= POSITION_END) || (POSITION_CENTER > POSITION_END && POSITION_CURRENT <= POSITION_END))
{
value = INTERPOLATION_END;
}
else
{
if (INTERPOLATION_END > INTERPOLATION_CENTER)
{
if (CURVE_END == 0)
{
value = INTERPOLATION_CENTER + ((INTERPOLATION_END - INTERPOLATION_CENTER) * ((POSITION_CURRENT - POSITION_CENTER) / (POSITION_END - POSITION_CENTER)));
}
else if (CURVE_END > 0)
{
value = INTERPOLATION_CENTER + (((INTERPOLATION_END - INTERPOLATION_CENTER) * ((POSITION_CURRENT - POSITION_CENTER) / (POSITION_END - POSITION_CENTER))) / ((CURVE_END + 1.0) - (CURVE_END * ((POSITION_CURRENT - POSITION_CENTER) / (POSITION_END - POSITION_CENTER)))));
}
else
{
value = INTERPOLATION_END - (((INTERPOLATION_END - INTERPOLATION_CENTER) * ((POSITION_CURRENT - POSITION_END) / (POSITION_CENTER - POSITION_END))) / (1.0 + (-CURVE_END * ((POSITION_CURRENT - POSITION_CENTER) / (POSITION_END - POSITION_CENTER)))));
}
}
else
{
if (CURVE_END == 0)
{
value = INTERPOLATION_CENTER - ((INTERPOLATION_CENTER - INTERPOLATION_END) * ((POSITION_CURRENT - POSITION_CENTER) / (POSITION_END - POSITION_CENTER)));
}
else if (CURVE_END > 0)
{
value = INTERPOLATION_CENTER - (((INTERPOLATION_CENTER - INTERPOLATION_END) * ((POSITION_CURRENT - POSITION_CENTER) / (POSITION_END - POSITION_CENTER))) / ((CURVE_END + 1.0) - (CURVE_END * ((POSITION_CURRENT - POSITION_CENTER) / (POSITION_END - POSITION_CENTER)))));
}
else
{
value = INTERPOLATION_END + (((INTERPOLATION_CENTER - INTERPOLATION_END) * ((POSITION_CURRENT - POSITION_END) / (POSITION_CENTER - POSITION_END))) / (1.0 + (-CURVE_END * ((POSITION_CURRENT - POSITION_CENTER) / (POSITION_END - POSITION_CENTER)))));
}
}
}
}
else
{
value = INTERPOLATION_CENTER;
}

return value;
}

Fonction range :
float range (const float RANGE_START, const float VALUE_CURRENT, const float RANGE_END)
{
float value = 0;

if (RANGE_START < RANGE_END)
{
if (VALUE_CURRENT <= RANGE_START)
{
value = RANGE_START;
}
else if (VALUE_CURRENT >= RANGE_END)
{
value = RANGE_END;
}
else
{
value = VALUE_CURRENT;
}
}
else if (RANGE_START > RANGE_END)
{
if (VALUE_CURRENT <= RANGE_END)
{
value = RANGE_END;
}
else if (VALUE_CURRENT >= RANGE_START)
{
value = RANGE_START;
}
else
{
value = VALUE_CURRENT;
}
}
else
{
value = RANGE_START;
}

return value;
}

Fonction center :
float center (const float VALUE_START, const float VALUE_END)
{
float value = 0;

if (VALUE_START == VALUE_END)
{
value = VALUE_START;
}
else
{
value = VALUE_START + ((VALUE_END - VALUE_START) / 2.0);
}

return value;
}

Fonction pow :
float pow (const float VALUE, const signed long EXPONENT)
{
signed long iterationPower = 0;
float value = 0;

if (EXPONENT < 0)
{
if (VALUE < 0)
{
value = -VALUE;
}
else
{
value = VALUE;
}

for (iterationPower = -1; iterationPower > EXPONENT; iterationPower--)
{
value *= VALUE;
}

value = 1.0 / value;

if (VALUE < 0)
{
value = -value;
}
}
else if (EXPONENT == 0)
{
if (VALUE < 0)
{
value = -1;
}
else
{
value = 1;
}
}
else
{
if (VALUE < 0)
{
value = -VALUE;
}
else
{
value = VALUE;
}

for (iterationPower = 1; iterationPower < EXPONENT; iterationPower++)
{
value *= VALUE;
}

if (VALUE < 0)
{
value = -value;
}
}

return value;
}

Fonction sqrt :
float sqrt (const float RADICAND)
{
unsigned char iterationPrecision = 0;
float searchDecimal = 0.1;
float foundDecimal = 0;
bool quickSearch = false;
unsigned long searchInteger = 1000;
unsigned int incrementInteger = 1000;
float sr1 = 0;
float sr2 = 0;
float sr3 = 0;
float value = 0;

if (RADICAND < 1)
{
while (searchDecimal * searchDecimal <= RADICAND)
{
searchDecimal += 0.1;
}

for (iterationPrecision = 0; iterationPrecision < 4; iterationPrecision++)
{
foundDecimal = ((RADICAND / searchDecimal) + searchDecimal) / 2.0;
searchDecimal = foundDecimal;
}

value = foundDecimal;
}
else if (RADICAND == 1)
{
value = 1;
}
else
{
while (quickSearch == false)
{
while (searchInteger * searchInteger <= RADICAND)
{
searchInteger += incrementInteger;
}

searchInteger -= incrementInteger;

if (incrementInteger == 1)
{
quickSearch = true;
}
else
{
incrementInteger /= 10;
}
}

sr1 = RADICAND - (float (searchInteger) * float (searchInteger));
sr2 = sr1 / (2.0 * float (searchInteger));
sr3 = float (searchInteger) + sr2;

value = sr3 - ((sr2 * sr2) / (2.0 * sr3));
}

return value;
}

Fonction fact :
unsigned long long fact (const unsigned long INTEGER)
{
unsigned long iterationFactorial = 1;
unsigned long long value = 1;

for (iterationFactorial = 1; iterationFactorial <= INTEGER; iterationFactorial++)
{
value *= iterationFactorial;
}

return value;
}

Fonction sin :
float sin (const float ANGLE)
{
unsigned long iterationModulo = 0;
unsigned long foundMultiply = 0;
bool quickSearch = false;
float angle = 0;
float alpha = 0;
float alpha2 = 0;
float alpha3 = 0;
float alpha5 = 0;
float sinus = 0;

if (ANGLE >= -180 && ANGLE <= 180)
{
angle = ANGLE;
}
else if (ANGLE < -180)
{
while (quickSearch == false)
{
for (iterationModulo = 1; ANGLE + (360.0 * (float (foundMultiply) + float (iterationModulo))) < -180; iterationModulo *= 10)
{
}

if (iterationModulo == 1)
{
quickSearch = true;
}
else
{
foundMultiply += iterationModulo / 10ul;
}
}

foundMultiply++;

angle = ANGLE + (360.0 * float (foundMultiply));
}
else
{
while (quickSearch == false)
{
for (iterationModulo = 1; ANGLE - (360.0 * (float (foundMultiply) + float (iterationModulo))) > 180; iterationModulo *= 10)
{
}

if (iterationModulo == 1)
{
quickSearch = true;
}
else
{
foundMultiply += iterationModulo / 10ul;
}
}

foundMultiply++;

angle = ANGLE - (360.0 * float (foundMultiply));
}

if (angle == -90 || angle == 270)
{
sinus = -1;
}
else if (angle == -270 || angle == 90)
{
sinus = 1;
}
else if (angle != -360 && angle != -180 && angle != 0 && angle != 180 && angle != 360)
{
alpha = angle * 0.0174532925199432;

alpha2 = alpha * alpha;
alpha3 = alpha2 * alpha;
alpha5 = alpha2 * alpha3;

sinus = alpha - (alpha3 / 6.0) + (alpha5 / 120.0) - ((alpha2 * alpha5) / 5040.0);
}

return sinus;
}

Fonction cos :
float cos (const float ANGLE)
{
unsigned long iterationModulo = 0;
unsigned long foundMultiply = 0;
bool quickSearch = false;
float angle = 0;
float alpha = 0;
float alpha2 = 0;
float alpha4 = 0;
float cosinus = 0;

if (ANGLE >= -180 && ANGLE <= 180)
{
angle = ANGLE;
}
else if (ANGLE < -180)
{
while (quickSearch == false)
{
for (iterationModulo = 1; ANGLE + (360.0 * (float (foundMultiply) + float (iterationModulo))) < -180; iterationModulo *= 10)
{
}

if (iterationModulo == 1)
{
quickSearch = true;
}
else
{
foundMultiply += iterationModulo / 10ul;
}
}

foundMultiply++;

angle = ANGLE + (360.0 * float (foundMultiply));
}
else
{
while (quickSearch == false)
{
for (iterationModulo = 1; ANGLE - (360.0 * (float (foundMultiply) + float (iterationModulo))) > 180; iterationModulo *= 10)
{
}

if (iterationModulo == 1)
{
quickSearch = true;
}
else
{
foundMultiply += iterationModulo / 10ul;
}
}

foundMultiply++;

angle = ANGLE - (360.0 * float (foundMultiply));
}

if (angle == -180 || angle == 180)
{
cosinus = -1;
}
else if (angle == -360 || angle == 0 || angle == 360)
{
cosinus = 1;
}
else if (angle != -270 && angle != -90 && angle != 90 && angle != 270)
{
alpha = angle * 0.0174532925199432;

alpha2 = alpha * alpha;
alpha4 = alpha2 * alpha2;

cosinus = 1.0 - ((alpha2 / 2.0) - (alpha4 / 24.0) + ((alpha2 * alpha4) / 720.0) - ((alpha4 * alpha4) / 40320.0));
}

return cosinus;
}

Fonction tan :
float tan (const float ANGLE)
{
unsigned long iterationModulo = 0;
unsigned long foundMultiply = 0;
bool quickSearch = false;
float angle = 0;
float alpha = 0;
float alpha2 = 0;
float alpha3 = 0;
float alpha5 = 0;
float tangent = 0;

if (ANGLE >= -90 && ANGLE <= 90)
{
angle = ANGLE;
}
else if (ANGLE < -90)
{
while (quickSearch == false)
{
for (iterationModulo = 1; ANGLE + (180.0 * (float (foundMultiply) + float (iterationModulo))) < -90; iterationModulo *= 10)
{
}

if (iterationModulo == 1)
{
quickSearch = true;
}
else
{
foundMultiply += iterationModulo / 10ul;
}
}

foundMultiply++;

angle = ANGLE + (180.0 * float (foundMultiply));
}
else
{
while (quickSearch == false)
{
for (iterationModulo = 1; ANGLE - (180.0 * (float (foundMultiply) + float (iterationModulo))) > 90; iterationModulo *= 10)
{
}

if (iterationModulo == 1)
{
quickSearch = true;
}
else
{
foundMultiply += iterationModulo / 10ul;
}
}

foundMultiply++;

angle = ANGLE - (180.0 * float (foundMultiply));
}

if (angle == -45)
{
tangent = -1;
}
else if (angle == -90 || angle == 0 || angle == 90)
{
tangent = 0;
}
else if (angle == 45)
{
tangent = 1;
}
else
{
if (angle > -45 && angle < 45)
{
alpha = angle * 0.0174532925199432;
}
else
{
if (angle < 0)
{
alpha = (-90.0 - angle) * 0.0174532925199432;
}
else
{
alpha = (90.0 - angle) * 0.0174532925199432;
}
}

alpha2 = alpha * alpha;
alpha3 = alpha2 * alpha;
alpha5 = alpha2 * alpha3;

if (angle > -45 && angle < 45)
{
tangent = alpha + ((alpha3 / 3.0) + ((2.0 * alpha5) / 15.0) + ((17.0 * (alpha5 * alpha2)) / 315.0));
}
else
{
tangent = 1.0 / (alpha + ((alpha3 / 3.0) + ((2.0 * alpha5) / 15.0) + ((17.0 * (alpha5 * alpha2)) / 315.0)));
}
}

return tangent;
}

Fonction arcsin :
float arcsin (const float SINUS)
{
float angle = 0;
float anglePrevious = 0;
float sinus = 0;
float sinusPositive = 0;
float alpha = 0;
float alpha2 = 0;
float alpha3 = 0;
float alpha5 = 0;
float incrementAngle = 10;
unsigned char decimal = 0;
unsigned char error = 0;
bool quickSearch = false;

if (SINUS <= -1)
{
angle = -90;
}
else if (SINUS == 0)
{
angle = 0;
}
else if (SINUS >= 1)
{
angle = 90;
}
else
{
if (SINUS < 0)
{
sinusPositive = -SINUS;
}
else
{
sinusPositive = SINUS;
}

while (quickSearch == false)
{
alpha = angle * 0.0174532925199432;

alpha2 = alpha * alpha;
alpha3 = alpha2 * alpha;
alpha5 = alpha2 * alpha3;

sinus = alpha - (alpha3 / 6.0) + (alpha5 / 120.0) - ((alpha2 * alpha5) / 5040.0);

if (sinus < sinusPositive && incrementAngle >= 1)
{
anglePrevious = angle;
angle += incrementAngle;
}
else if (sinus < sinusPositive && incrementAngle < 1 && error < 9)
{
anglePrevious = angle;
angle += incrementAngle;

error++;
}
else if (sinus == sinusPositive || decimal == 4 + 1)
{
quickSearch = true;
}
else
{
incrementAngle /= 10;
angle = anglePrevious + incrementAngle;

decimal++;
error = 0;
}

if (angle > 90.0001)
{
angle = 89.9999;
quickSearch = true;
}
}

if (SINUS < 0)
{
angle = -angle;
}
}

return angle;
}

Fonction arccos :
float arccos (const float COSINUS)
{
float angle = 0;
float anglePrevious = 0;
float cosinus = 0;
float cosinusPositive = 0;
float alpha = 0;
float alpha2 = 0;
float alpha4 = 0;
float incrementAngle = 10;
unsigned char decimal = 0;
unsigned char error = 0;
bool quickSearch = false;

if (COSINUS <= -1)
{
angle = 180;
}
else if (COSINUS == 0)
{
angle = 90;
}
else if (COSINUS >= 1)
{
angle = 0;
}
else
{
if (COSINUS < 0)
{
cosinusPositive = -COSINUS;
}
else
{
cosinusPositive = COSINUS;
}

while (quickSearch == false)
{
alpha = angle * 0.0174532925199432;

alpha2 = alpha * alpha;
alpha4 = alpha2 * alpha2;

cosinus = 1.0 - ((alpha2 / 2.0) - (alpha4 / 24.0) + ((alpha2 * alpha4) / 720.0) - ((alpha4 * alpha4) / 40320.0));

if (cosinus > cosinusPositive && incrementAngle >= 1)
{
anglePrevious = angle;
angle += incrementAngle;
}
else if (cosinus > cosinusPositive && incrementAngle < 1 && error < 9)
{
anglePrevious = angle;
angle += incrementAngle;

error++;
}
else if (cosinus == cosinusPositive || decimal == 4 + 1)
{
quickSearch = true;
}
else
{
incrementAngle /= 10;
angle = anglePrevious + incrementAngle;

decimal++;
error = 0;
}

if (angle > 90.0001)
{
angle = 89.9999;
quickSearch = true;
}
}

if (COSINUS < 0)
{
angle = 180.0 - angle;
}
}

return angle;
}

Fonction arctan :
float arctan (const float TANGENT)
{
float angle = 0;
float anglePrevious = 0;
float sinus = 0;
float cosinus = 0;
float tangent = 0;
float tangentPositive = 0;
float alpha = 0;
float alpha2 = 0;
float alpha3 = 0;
float alpha4 = 0;
float alpha5 = 0;
float incrementAngle = 10;
unsigned char decimal = 0;
unsigned char error = 0;
bool quickSearch = false;

if (TANGENT <= -9999999999999999)
{
angle = -90;
}
else if (TANGENT == -1)
{
angle = -45;
}
else if (TANGENT == 0)
{
angle = 0;
}
else if (TANGENT == 1)
{
angle = 45;
}
else if (TANGENT >= 9999999999999999)
{
angle = 90;
}
else
{
if (TANGENT < 0)
{
tangentPositive = -TANGENT;
}
else
{
tangentPositive = TANGENT;
}

while (quickSearch == false)
{
alpha = angle * 0.0174532925199432;

alpha2 = alpha * alpha;
alpha3 = alpha2 * alpha;
alpha4 = alpha2 * alpha2;
alpha5 = alpha2 * alpha3;

sinus = alpha - (alpha3 / 6.0) + (alpha5 / 120.0) - ((alpha2 * alpha5) / 5040.0);
cosinus = 1.0 - ((alpha2 / 2.0) - (alpha4 / 24.0) + ((alpha2 * alpha4) / 720.0) - ((alpha4 * alpha4) / 40320.0));
tangent = sinus / cosinus;

if (tangent < tangentPositive && incrementAngle >= 1)
{
anglePrevious = angle;
angle += incrementAngle;
}
else if (tangent < tangentPositive && incrementAngle < 1 && error < 9)
{
anglePrevious = angle;
angle += incrementAngle;

error++;
}
else if (tangent == tangentPositive || decimal == 4 + 1)
{
quickSearch = true;
}
else
{
incrementAngle /= 10;
angle = anglePrevious + incrementAngle;

decimal++;
error = 0;
}

if (angle > 90.0001)
{
angle = 89.9999;
quickSearch = true;
}
}

if (TANGENT < 0)
{
angle = -angle;
}
}

return angle;
}

Fonction arctan2 :
float arctan2 (const float X, const float Y)
{
const float TANGENT = Y / X;
float angle = 0;
float anglePrevious = 0;
float sinus = 0;
float cosinus = 0;
float tangent = 0;
float tangentPositive = 0;
float alpha = 0;
float alpha2 = 0;
float alpha3 = 0;
float alpha4 = 0;
float alpha5 = 0;
float incrementAngle = 10;
unsigned char decimal = 0;
unsigned char error = 0;
bool quickSearch = false;

if (TANGENT <= -9999999999999999)
{
angle = -90;
}
else if (TANGENT == -1)
{
angle = -45;
}
else if (TANGENT == 0)
{
angle = 0;
}
else if (TANGENT == 1)
{
angle = 45;
}
else if (TANGENT >= 9999999999999999)
{
angle = 90;
}
else
{
if (TANGENT < 0)
{
tangentPositive = -TANGENT;
}
else
{
tangentPositive = TANGENT;
}

while (quickSearch == false)
{
alpha = angle * 0.0174532925199432;

alpha2 = alpha * alpha;
alpha3 = alpha2 * alpha;
alpha4 = alpha2 * alpha2;
alpha5 = alpha2 * alpha3;

sinus = alpha - (alpha3 / 6.0) + (alpha5 / 120.0) - ((alpha2 * alpha5) / 5040.0);
cosinus = 1.0 - ((alpha2 / 2.0) - (alpha4 / 24.0) + ((alpha2 * alpha4) / 720.0) - ((alpha4 * alpha4) / 40320.0));
tangent = sinus / cosinus;

if (tangent < tangentPositive && incrementAngle >= 1)
{
anglePrevious = angle;
angle += incrementAngle;
}
else if (tangent < tangentPositive && incrementAngle < 1 && error < 9)
{
anglePrevious = angle;
angle += incrementAngle;

error++;
}
else if (tangent == tangentPositive || decimal == 4 + 1)
{
quickSearch = true;
}
else
{
incrementAngle /= 10;
angle = anglePrevious + incrementAngle;

decimal++;
error = 0;
}

if (angle > 90.0001)
{
angle = 89.9999;
quickSearch = true;
}
}

if (TANGENT < 0)
{
angle = -angle;
}
}

if (X < 0)
{
if (Y >= 0)
{
angle += 180;
}
else
{
angle -= 180;
}
}

return angle;
}




Exemples pour se servir des fonctions

Arrondir des nombres décimaux :

Des calculs complexes en virgule flottante (float), comprenez en nombre décimaux, sont parfois nécessaires afin de conserver la précision tout au long des opérations arithmétiques. Mais la finalité de ces opérations se retrouveront souvent dans un but de faire fonctionner des systèmes prenant en entrée uniquement des nombres entiers. Il est donc nécessaire d'arrondir le résultat en toute fin du calcul.

Exemple pour arrondir un nombre décimal à l'entier inférieur :
int main()
{
floor (14.6);
//la fonction retourne la valeur 14

return 0;
}

Dans l'exemple ci-dessus, la fonction statique floor est appelée, elle prend en paramètre 14.6, le nombre décimal à arrondir à l'entier inférieur, et retourne (dans ce cas de figure) le nombre entier 14.

Exemple pour arrondir un nombre décimal à l'entier le plus proche :
int main()
{
round (23.7);
//la fonction retourne la valeur 24

return 0;
}

Dans cet exemple la fonction statique round est appelée, elle prend en paramètre 23.7, le nombre décimal à arrondir à l'entier le plus proche, et retourne le nombre entier 24.

Exemple pour arrondir un nombre décimal à l'entier supérieur :
int main()
{
ceil (5.12);
//la fonction retourne la valeur 6

return 0;
}

Ici la fonction statique ceil est appelée, elle prend en paramètre 5.12, le nombre décimal à arrondir à l'entier supérieur, et retourne le nombre entier 6.



Créer des interpolations de courbes :

Il est très simple avec les fonctions de courbes que je propose de changer des valeurs d'échelle, d'interpoler des courbes vers d'autres valeurs, tout en ajoutant de l'exponentiel afin d'adoucir ou de rendre plus vif l'évolution des courbes ainsi créées. Il est également possible de créer des interpolations dissymétriques autour d'un centre arbitraire, mettant en jeu de part et d'autre deux types d'interpolations différentes (linéaires et exponentielles positives et négatives).

Exemple pour créer une interpolation linéaire d'une courbe :
int main()
{
curve (-25, 50, 100, 1, 10, 0);
//la fonction retourne la valeur 6.4

return 0;
}

Dans l'exemple ci-dessus, la fonction statique curve est appelée prenant plusieurs paramètres :
- Le 1er paramètre -25 est le point initial de la courbe.
- Le 2ème paramètre 50 est le point courant de la courbe.
- Le 3ème paramètre 100 est le point final de la courbe.
- Le 4ème paramètre 1 est le point initial de l'interpolation souhaitée.
- Le 5ème paramètre 10 est le point final de l'interpolation souhaitée.
- Le 6ème paramètre 0 défini le type d'interpolation (0 = linéaire) à partir du point initial vers le point final.

Le résultat du calcul est 6.4.

À noter que les valeurs indiquées en paramètre peuvent indifféremment être positives ou négatives et inférieures ou supérieures les unes par rapport aux autres, la fonction curve est prévue à cet effet.

Exemple pour créer une interpolation exponentielle d'une courbe :
int main()
{
curve (-25, 50, 100, 1, 10, 40);
//la fonction retourne la valeur ≈ 1.317 (valeur arrondie)

return 0;
}

L'exemple est identique au précédent, sauf le 6ème paramètre 40 (différent de 0 donc non-linéaire) qui permet une interpolation exponentielle positive, plus ce nombre est élevé, plus l'exponentielle est prononcée. Un nombre négatif produit une exponentielle négative, c'est-à-dire non pas une interpolation exponentielle qui évolue doucement proche du point initial de la courbe, mais plutôt évoluant rapidement proche du point initial pour terminer plus douce à l'approche du point final.

Le résultat du calcul est maintenant ≈ 1.317 (valeur arrondie).

Exemple pour créer une interpolation linéaire dissymétrique d'une courbe :
int main()
{
wurve (0, 50, 70, 0, 9, 10, 0, 0);
//la fonction retourne la valeur ≈ 9.428 (valeur arrondie)

return 0;
}

Dans l'exemple ci-dessus la fonction statique wurve est appelée, voici le détail des paramètres (similaires à la fonction statique curve) :
- Le 1er paramètre 0 est le point initial de la courbe.
- Le 2ème paramètre 50 est le point courant de la courbe.
- Le 3ème paramètre 70 est le point final de la courbe.
- Le 4ème paramètre 0 est le point initial de l'interpolation souhaitée.
- Le 5ème paramètre 9 est le point central de l'interpolation souhaitée.
- Le 6ème paramètre 10 est le point final de l'interpolation souhaitée.
- Le 7ème paramètre 0 défini le type d'interpolation (0 = linéaire) à partir du point central vers le point initial.
- Le 8ème paramètre 0 défini le type d'interpolation (0 = linéaire) à partir du point central vers le point final.

Le résultat du calcul est ≈ 9.428 (valeur arrondie).

À l'instar de la fonction curve, les valeurs indiquées en paramètre avec la fonction wurve peuvent indifféremment être positives ou négatives et inférieures ou supérieures les unes par rapport aux autres.

Exemple pour créer une interpolation double exponentielle centrée d'une courbe :
int main()
{
wurve (0, 473, 1023, 1000, 1500, 2000, 20, 20);
//la fonction retourne la valeur ≈ 1498.069 (valeur arrondie)

return 0;
}

Ci-dessus la fonction statique wurve prend en entrée la valeur d'un potentiomètre pouvant varier de 0 à 1023, c'est la courbe à interpoler, les valeurs d'interpolation vont de 1000 à 2000 en passant par un centre à 1500, ce centre sert à créer une double exponentielle centrée sur 1500 ayant des valeurs de 20 (non-linéaire) de part et d'autre de ce point central (ou neutre).

Le résultat du calcul est ≈ 1498.069 (valeur arrondie).

Cette simple expression pourrait servir à transposer un ordre analogique via un potentiomètre (0 à 1023) vers un signal PWM (pouvant varier de 1000 à 2000 microsecondes) dans le but d'asservir un servo-moteur.

Beaucoup de mes projets utilisent les fonctions de courbes, car elles permettent de transposer facilement des valeurs d'un domaine vers un autre, sans pour autant compliquer la programmation (une ligne de programme est utilisée soit un seul appel de fonction et quelques paramètres).



Cadrer une valeur dans un intervalle :

Il peut être utile de solliciter une fonction dédiée lorsque nous souhaitons qu'une valeur ne sorte pas d'un certain intervalle, sans être obligé de rajouter les conditions logiques nécessaires à cette fonctionnalité dans notre programme (si inférieur ou égal à, si supérieur ou égal à, etc...), ce qui permet de diminuer le nombre d'instructions visibles et d'augmenter la lisibilité du code source.

Exemple pour cadrer une valeur dans un intervalle :
int main()
{
range (-10, 23, 10);
//la fonction retourne une valeur qui ne sortira jamais de l'intervalle -10 à 10

return 0;
}

Dans l'exemple ci-dessus, la fonction statique range limite l'intervalle que peut prendre le nombre 23, ceci dans un cadre -10 à 10. La fonction retourne alors le nombre 10.

Les valeurs indiquées en paramètre peuvent indifféremment être positives ou négatives et inférieures ou supérieures les unes par rapport aux autres, la fonction range est implémentée à cet effet.



Calculer la moyenne de deux valeurs :

De même que la fonction présentée ci-dessus, une fonction pour trouver la moyenne de deux nombres (ou centre) semble facultative, néanmoins elle reste bien pratique !

Exemple pour calculer la moyenne de deux valeurs :
int main()
{
center (125, 85.3);
//la fonction retourne la valeur 105.15

return 0;
}

Dans l'exemple ci-dessus la fonction statique center prend en paramètre les nombres 125 et 85.3, elle retourne donc la moyenne de ces deux nombre, soit 105.15.

L'ordre des nombres indiqués en paramètre à la fonction statique center peuvent être permutés indifféremment.



Calculer la puissance d'un nombre :

La puissance d'un nombre est le résultat de la multiplication répétée (via un exposant) de ce nombre avec lui même.

Exemple pour calculer la puissance d'un nombre :
int main()
{
pow (5, 4);
//la fonction retourne la valeur 625

return 0;
}

Ici le nombre 5 représente le nombre à multiplier avec lui-même, 4 est l'exposant, soit le calcul 5 x 5 x 5 x 5 = 625.

Le nombre à multiplier avec lui même ainsi que l'exposant peuvent être positifs, nuls, ou négatifs.



Calculer la racine carrée d'un nombre :

Le résultat de la racine carrée d'un nombre, est un nombre qui, multiplié par lui-même, donne le radicande (soit le nombre entré en paramètre à la fonction).

Exemple pour calculer la racine carrée d'un nombre :
int main()
{
sqrt (25);
//la fonction retourne la valeur 5

return 0;
}

Ci-dessus le nombre 25 est le résultat du nombre 5 multiplié par lui-même (5 x 5 = 25), la fonction retourne donc le nombre 5.



Calculer la factorielle d'un nombre :

La factorielle d'un nombre est le produit des nombres entiers strictement positifs inférieurs ou égaux à ce nombre. Cet algèbre permet d'effectuer des approches du nombre Pi, de faire converger des équations pour obtenir le sinus, le cosinus, etc...

Exemple pour calculer la factorielle d'un nombre :
int main()
{
fact (7);
//la fonction retourne la valeur 5040

return 0;
}

Dans l'exemple ci-dessus la factorielle du nombre 7 entré en paramètre donne le résultat 5040, car 1 x 2 x 3 x 4 x 5 x 6 x 7 = 5040.

Par convention la factorielle du nombre 0 est 1.



Les fonctions sinus, cosinus, et tangente :

Les fonctions trigonométriques élémentaires comme sinus, cosinus, ou encore tangente s'avèrent utiles dans le domaine des automates programmables afin d'obtenir la position angulaire d'un robot, calculer la trajectoire d'un objet à l'aide d'un gyroscope, etc...

Attention, mes fonctions trigonométriques sin (sinus), cos (cosinus), et tan (tangente) prennent en entrée un angle en degrés (et non pas en radians).

Exemple pour calculer le sinus d'un angle :
int main()
{
sin (30);
//la fonction retourne la valeur 0.5

return 0;
}

Dans cet exemple le sinus de l'angle 30 degrés est 0.5.

Exemple pour calculer le cosinus d'un angle :
int main()
{
cos (45);
//la fonction retourne la valeur ≈ 0.707 (valeur arrondie)

return 0;
}

Dans l'exemple ci-dessus, le cosinus de l'angle 45 degrés est ≈ 0.707 (valeur arrondie).

Exemple pour calculer la tangente d'un angle :
int main()
{
tan (45);
//la fonction retourne la valeur 1

return 0;
}

Ci-dessus la tangente de l'angle 45 degrés est 1.



Les fonctions réciproques arc sinus, arc cosinus, arc tangente, et arc tangente 2 :

En complément des fonctions sinus, cosinus, et tangente, il est fort utile de disposer des fonctions réciproques comme arc sinus, arc cosinus, arc tangente, et arc tangente 2.

Attention, mes fonctions trigonométriques arcsin (arc sinus), arccos (arc cosinus), arctan (arc tangente), et arctan2 (arc tangente à partir de deux arguments x et y) retournent en sortie un angle en degrés (et non pas en radians).

Exemple pour trouver l'angle à partir d'un sinus :
int main()
{
arcsin (0.5);
//la fonction retourne la valeur 30

return 0;
}

Dans l'exemple ci-dessus, un sinus de 0.5 correspond à un angle de 30 degrés.

Exemple pour trouver l'angle à partir d'un cosinus :
int main()
{
arccos (0.707);
//la fonction retourne la valeur ≈ 45.008 (valeur arrondie)

return 0;
}

Avec la fonction statique arccos, on trouve qu'un cosinus de 0.707 correspond à un angle de ≈ 45.008 degrés (valeur arrondie).

Exemple pour trouver l'angle à partir d'une tangente :
int main()
{
arctan (1);
//la fonction retourne la valeur 45

return 0;
}

Une tangente de 1 correspond à un angle de 45 degrés.

Exemple pour trouver l'angle à partir de la tangente de deux arguments x et y (ou fonction circulaire réciproque à quatre cadrans) :
int main()
{
arctan2 (0.5, 0.5);
//la fonction retourne la valeur 45

return 0;
}

Dans l'exemple ci-dessus, une tangente à partir de deux arguments x égal à 0.5 et y égal à 0.5 correspond à un angle de 45 degrés.



Récapitulatif des paramètres des fonctions :

static signed long floor (const float VALUE);
static signed long round (const float VALUE);
static signed long ceil (const float VALUE);
static float curve (const float POSITION_START, const float POSITION_CURRENT, const float POSITION_END, const float INTERPOLATION_START, const float INTERPOLATION_END, const float CURVE);
static float wurve (const float POSITION_START, const float POSITION_CURRENT, const float POSITION_END, const float INTERPOLATION_START, const float INTERPOLATION_CENTER, const float INTERPOLATION_END, const float CURVE_START, const float CURVE_END);
static float range (const float RANGE_START, const float VALUE_CURRENT, const float RANGE_END);
static float center (const float VALUE_START, const float VALUE_END);
static float pow (const float NUMBER, const unsigned long EXPONENT);
static float sqrt (const float RADICAND);
static unsigned long long fact (const unsigned long INTEGER);
static float sin (const float ANGLE);
static float cos (const float ANGLE);
static float tan (const float ANGLE);
static float arcsin (const float SINUS);
static float arccos (const float COSINUS);
static float arctan (const float TANGENT);
static float arctan2 (const float X, const float Y);



Les fonctions ci-dessus simplifient grandement la mise en œuvre de nombreuses applications, vous pouvez combiner les fonctions entres-elles et obtenir des résultats étonnants de complexité !

Si vos applications requièrent des fonctions mathématiques qui ne sont pas présentes ici, libre à vous d'en ajouter si besoin ;)

4
Bonjour à vous :)

Citer
Ce que je souhaite partager avec vous : Conversion d'images bitmap vers une sérigraphie KiCad via une routine bash (.sh)

Avec cette routine de conversion d'images (pour le système d'exploitation Linux), vous allez pouvoir importer des logos (et autres graphismes) dans vos dessins KiCad en vue PCB sur le calque de sérigraphie de la face avant (F.SilkS).

Il existe un outil par défaut dans cette suite KiCad nommé Bitmap2Component qui est censé remplir cette fonction, mais notamment dépendant de la résolution (hauteur/largeur) de l'image d'origine, il ne permet pas le redimensionnement, est basé sur un principe de conversion vectorielle qui détruit l'information, et au final fait apparaître pour certains dessins de petites tailles des lignes courbes là où il y a des droites parfaites, et plus une bouillie de pixels qu'une sérigraphie de qualité...

Ainsi cet outil proposé par défaut est pour moi inutilisable lorsque l'on souhaite un rendu exact par rapport à notre image noir et blanc initiale.

À l'instar de Bitmap2Component, ma routine d'automatisation prend en entrée une image qui doit être initialement en noir et blanc (monochrome) afin que les pixels blancs soient utilisés dans le traitement :

Citer
Ce que je vous propose ici permettra qu'un pixel blanc dans votre image d'origine sera très exactement un carré de sérigraphie (de la taille souhaitée) dans votre dessin en vue PCB.

Ci-dessous, la routine (.sh) permettant la conversion d'images bitmap (.bmp) vers KiCad (.mod) :

#!/bin/bash

echo "Pixel size in mil ?"
read sizeRaw

clear

rm tmp -r -f
mkdir tmp

size=$(echo $sizeRaw"*10" | bc -l)

for file in *.bmp
do
if [ -f "$file" ]
then
echo $file" to "${file%%.*}.mod

convert "$file" tmp/tmp.txt

grep "white" tmp/tmp.txt > tmp/tmp
grep -o ".*:" tmp/tmp > tmp/tmpxy
grep -o ".*," tmp/tmpxy > tmp/x
sed -i tmp/x -e "s/,//"
grep -o ",.*:" tmp/tmpxy > tmp/y
sed -i tmp/y -e "s/,//" -e "s/://"

countList=0

while read x
do
xList[countList]=$(echo $x"*"$size | bc -l)
((countList++))
done < tmp/x

countList=0

while read y
do
yList[countList]=$(echo $y"*"$size | bc -l)
((countList++))
done < tmp/y

echo "PCBNEW-LibModule-V1" > tmp/tmp.mod
echo "\$INDEX" >> tmp/tmp.mod
echo ${file%%.*} >> tmp/tmp.mod
echo "\$EndINDEX" >> tmp/tmp.mod
echo "\$MODULE "${file%%.*} >> tmp/tmp.mod
echo "Li "${file%%.*} >> tmp/tmp.mod

for ((iterationList=0; iterationList < countList; iterationList++))
do
echo "DP 0 0 0 0 4 0 200" >> tmp/tmp.mod
echo "Dl "${xList[iterationList]}" "${yList[iterationList]} >> tmp/tmp.mod
echo "Dl "$(echo ${xList[iterationList]}"+"$size | bc -l)" "${yList[iterationList]} >> tmp/tmp.mod
echo "Dl "$(echo ${xList[iterationList]}"+"$size | bc -l)" "$(echo ${yList[iterationList]}"+"$size | bc -l) >> tmp/tmp.mod
echo "Dl "${xList[iterationList]}" "$(echo ${yList[iterationList]}"+"$size | bc -l) >> tmp/tmp.mod
done

echo "\$EndMODULE "${file%%.*} >> tmp/tmp.mod
echo "\$EndLIBRARY" >> tmp/tmp.mod

mv tmp/tmp.mod "${file%%.*}".mod
fi
done

rm tmp -r -f

exit 0

La routine présentée ci-dessus utilise le programme (ou paquet) imagemagick pour extraire les valeurs matricielles des images traitées.

Il vous faut donc l'installer à l'aide de la ligne de commande suivante (à écrire dans le terminal de Linux) :

sudo apt-get install imagemagick -y
Une fois cette installation effectuée, lorsque vous exécutez la routine (.sh) se propose à vous une question "Pixel size in mil ?", il vous faut alors renseigner la taille souhaitée en millième de pouce que fera un pixel dans votre dessin KiCad (cohérent lorsque les unités de mesures sont indiquées en pouces et non pas en millimètres) :

Par exemple si vous indiquez en taille de pixel le nombre 25, avec une grille dans votre dessin KiCad réglée sur 25 (et des unités de mesures en pouces) vous verrez que le pas des pixels de votre graphisme en vue PCB fera très exactement le même pas que la grille.

Après avoir validé le choix de la taille des pixels, toutes les images ayant l'extension .bmp (bitmap) dans le répertoire courant sont converties successivement en fichiers .mod (footprint) que vous pouvez ajouter à vos projets KiCad par l'intermédiaire du menu d'ajout de bibliothèques (Preferences > Library) en vue PCB.

Si vous apercevez le crénelage des pixels de votre graphisme sérigraphié une fois votre circuit réalisé, je vous conseille d'utiliser une image bitmap (.bmp) initiale de plus grande résolution, et d'indiquer une taille de pixel (lors de la conversion avec la routine) d'autant plus faible, par exemple 2.5 (attention cependant, les temps de traitement peuvent s'avérer assez longs avec des résolutions d'images trop grandes).

Libre à vous de faire une utilisation de ce petit programme de conversion d'image, qui vous permettra aisément d'apposer vos logos et divers graphismes sur vos circuits imprimés avec une parfaite exactitude de conversion (1 pixel bitmap vers 1 pixel sérigraphié).

Ci-dessous un exemple de code matriciel (QR Code) sérigraphié avec mon outil :


5
Vos projets et Montages d'Électronique / Re : Les livres de sauvegarde
« le: novembre 24, 2020, 09:16:35 am »
Bonjour, merci pour vos messages d'encouragement :)

Effectivement je persévère en tant que poisson qui nage à contre courant, mais l'important dans cette histoire c'est de partager avec vous des projets libres dans la gratuité et la volonté que vous puissiez éventuellement en trouver un intérêt.

Tout à fait rikigeek, c'est surtout orienté code et texte "brut", du moment que les caractères du texte en question se trouvent dans la norme UTF-8 (choix arbitraire de ma part mais réfléchi au vue du grand nombre de personnes à utiliser ce format).

C'est une bonne question pour les .odt et .docx. Je n'ai pas mon pc avec linux ubuntu cette semaine, je pourrais vous en dire plus samedi quand je serais à mon atelier, mais dans l'idée même si la base semble être du xml d'après ce que j'ai lu, après avoir ouvert un .odt (sous windows) je pense que ça ne fonctionnera pas.

J'ai écrit simplement dans un odt :
Test
é »(‘(è-è_è_i*/-+

fghfhrty’(-

Et voici le contenu que je vois dans notepad++ :
PK    ÅHxQ^Æ2 '   '      mimetypeapplication/vnd.oasis.opendocument.textPK    ÅHxQ               Configurations2/progressbar/PK    ÅHxQ               Configurations2/menubar/PK    ÅHxQ               Configurations2/popupmenu/PK    ÅHxQ               Configurations2/statusbar/PK    ÅHxQ               Configurations2/toolbar/PK    ÅHxQ               Configurations2/accelerator/PK    ÅHxQ               Configurations2/floater/PK    ÅHxQ               Configurations2/toolpanel/PK    ÅHxQ               Configurations2/images/Bitmaps/PK  ÅHxQ               manifest.rdfÍ“Ínƒ0„ï<…eÎØ@/r(ʹjŸÀ5†X/òšÞ¾Ž“VQ¤ªêŸÔã®F3ߎ´›íaÈ‹²¨ÁT4c)%ÊHhµé+:».¹¥Û:Úض+šñjƒ¥Ÿ*ºwn*9_–…-7 lϳ¢(xšó<O¼"ÁÕ8qH Æ´Ž Biõä|9Îâ fWQtë y÷ =‹Ý:© ²
a¶R½‡¶ ‘@ LÊ„tƒºNKÅ3–óQ9Á¡íâÇ`½Óƒ¢<`ð+ŽÏØÞˆ ¦å^཰î\ƒß|•hzîczuÓÅñß#”`œ2îOê»;yÿçþ.Ïÿ⯴vDl@Σgúç´òUG¯PK´÷hÒ  ƒ  PK  ÅHxQ           
   styles.xmlíKoÛ6ø¾_ahØn´,;ic¯é†
h;`é;´DY\)Q )?úë÷‘%J–5i7 sÌïýäGR¯~<æl¶'BR^ÜÑ|ÌHó„»ûà÷?£»àÇ×ß¼âiJc²Ix\å¤PHª#rÄ…ÜäDáû ņcIå¦À9‘oxI
G²iq7FŒýmO¥®ÕðèS>•ö(J9Šy^bE·¬Ã†sà“)UnÂPÓZAs.vár±¸ ío‡}d´øØà‡ùaep£õz¨CM⯬3XIF´j2ŒæQèpS§šc}9ª©ÄקM>L¥Õ¸]òU2|•ø´r¿›lò~7¾8Ãb²ñÙ§¥ºüÛP’ Õøo§GÉ û²Š*ß1ÙYXá³@C®.&ëAPE„‡_D1‹Ûrœ^Š Ó²ã”ËE´
R2Úf¬Ø5½%åUvC?ªå“cIÕ Ì Ù¦Ã¡ŸÇµˆ¡ÆqøŒ?A…º y:
‰抡‘>Ȇs”KD ˆ/7µÏ.Ç*é4wá[ šoß´ýPäSC¨q;¥ ZN.#‹Ýñ>χT…ØG!` ²×-¯i¢™ÊÙxÕP‡ºI2ˆ
¬W!4T(´§äðm“]R®ÔÅûßC
Cº†ÝMè±ôu{@RoÓ\¯Ý™rØS”˜Éׯlù6Ë3û[;ö>xSÅ4Á³\È(˜A{sx9e§ûà{\rùƒ‡d‚Y‡§ÆE;R@fAË•2‘K¡™üž= Y:.»‡8AÁs\t0JªbÈá=Ô4€ÏPlž¤Ûçøæ9ªµ¡øRá:IEòçèô–Æ‚KžªÙŸøBGõêáý#º½{ ùCU èÔBž+?+¼zÝNªNÏ„¤¸bõüê8×:í.3·þJhÏD(
ó®¶C*Á?D‡}üÛÕÍ‹[|Ìô¶í›±òr¹Nc¨­”oÀ
ñR™~Qp¤×$2à ? ÐV…Ž÷Áb¾ŠóAà©T0Ç 6 ’%Ža&Cô×Û‹F]Þ]DÞk£âsTèôS¹ž¡ð¬ÌÀŽU²sjŠ™ôò§Äw¼m@áJq-’Š&„[TÌÊ ;F­ s•ƒèqHë–óÈ™@jÛI*Z$Dooú\ãã”t:ÂøyÃK©³n\í]ë}fM% ¸¡ÐQ5ÂëdQ¢‚Å\‹W:Øßuôëݐ_.é'€GËR™5†‹]…w°”
³ÃT£ðýù÷ÆiDÁô>Qƒ­=™F\ ׬–éàÑb~[6^wâôSæ µðÓ»s‰zÊgäØï¸=¹
–µ¹'·f´/¹ýú.hƒÙé
SFýàbƒë¹€L-ä}°´í€Bü›_Ù©ÌHaBŠNˆQÔt
FsÚØ6±ʪˆUeêN. §@€¯—ã(¡Ð1
-¦üÛ¨-än5•à鶊¯)ÿŸHy?éˆërýL$Ç´@ú°ìÒñ<]ËJf}Q Ò8Æ¥ôšþS+Ξ ½†ÌˆŸoö´½åBאNP؇ Û×Ùÿ\ÁHðCO8¬ôJý#!%R|GT¦ÏùºZì ´ÿ µ—`‘£Ç…—a ŽÕ…×–á9¿_N¼úe ÍíV¥Ð5î#¼‡…ËŇ-ONCj=Ös, 7ËJ=4Ü,ÍÐЮo¹Rú\ óD´lÛP %Ü+ÌúÛu3mfÚÀì€Oò±F5ÒrL!ºŽóõÏ ýævÓúY:þÏ$טO;8ê±QÜÁ[åÇå ö¼Z›ïóX-í¨

ƸmÛÕv´åüH•l¬%Ã'¯xf>ø9¥ù䪭¸›—S+ÎŒ¡» Ê-Šn¿›î¥70j<Åü ‡i–Š½“¢Ë©)}½u·7Ó<÷6GÊ/˜;à*?³e×}ù9-Û¼GØ«qs“]ˆI.ws¾oã#c¡]Ó02Ã)Îø““Àú¬†ÿkI2m4ôlh൓³ìW8¿`ŽQÃïbŽ}¡|øïUº1WÊÞCœ…â7 zˆŒì «Ñ­ƒôÚ mUŽôm?†æÜx^7Éš´ïzÄ%5S<ÄÒÔ-q)x `H¥]¡_†ØöPjÞf1…±œH‚¶'Û®ažöÜ1¨@ÇÌžèåÕ!]‡¬®é:äæꐮCn¯é:äÅÕ!]‡¼¼:¤ë»«CºY_ÒÌÿ#tA¾›
®ˆ„™¸H鮪ïÑ ª )çJÿòXTìë泊è]t„²ñTý^áÓØS„~ÐÐüÜ'.ÚÞé’"S+èØk´ ‰=Ù7aseº^·‡ì!ïÔLZ/0’ªF‹X˜OõNï=§ní+º¾Æžp‚q wzÛA´ñ ¢Ûý*¡Ì£` ©wZ7Mô7NËh¾XDõM‚¸ë¤åzþrÔÂZ8P!.¨þ¶ª5J`ª‚þÅÈmEoYûèlQÔ
=‡õ—mþ¡[ô][ûÑD IéØY_,æ‹è®âãЖ€å_ãD‹h §ú}k¥­?8rF›ƒ9Nþª¤²Y`sî (bÛæeÎ}ß°0ÿ>ggmF°~–1?BßÞâ9£6#ÏS°äX6<iõ¢ætñeÅ×ÙK]¯zìÃáO¡_ÿ
PKçc±  J-  PK  ÅHxQ               meta.xml“ËŽÛ †÷}
‹vk¾9ž]W•Z©©Ú]DàÄ¡uÀÂd<}û_2™IõŽÿ|?ç†ë§—S<ƒ”ÑD#‚ÐÂH¥Û
ú±ý–è©ùP›ÃA `Òˆó ´ Oàxà­z`­•²Û £s=ÃxÇhL"c[’àKîxø¬`üˆÇżAg«™áƒ˜æ'˜Ìô ×ì•eSYóy.äÝKÙ·~c®µ^ 3±Ö›âù¼Ò/ÒõF«ªÂStE¥¸rýÙv%†.õ ˜F£`)èfà jÖé^zmê©ca;O„~zÐÄ$&!¥aœn)a$cI•YF¦¯Æµì‘5g”DY^­Ö›³‚TÎ/>”g;ÝÕ|Û&ñ÷%Á]ð­Gü
}G/òÌ^ŸÏàüƒS"˜tÇ÷„ÂœµÛ ¿ªIT'ÞÞ‰fÿ„{¯ö7$½j–·–÷Ç5,ÑX¹j颉£§…{…ã%¢ýDÇ£r0ô\ø$w Exé®
~4Æ6_ÔÞÂ×i©¸ˆH”DôÓOåç8ì~•ù.Oƒd×[sé
Ë"K‹2+%¡©LÅ!¯Ê¢”{ZT2‰óƒHÒ2RÆˈ_óÕøÍ ÂþÖæPK×%®úÏ  ë  PK  ÅHxQ               settings.xmlµZQsâ8 ~¿_Ñá½KÙöz-Óv'вË-- Ðíܾ™D@®Ž•±ÿþdØ…–%ÑS§Ä‘,YúôIÎÕ—y"^@›Õu¥öé¤r*Ä(V“ëÊã°u|QùróÇŽÇqõÃ,e
XKK̽®L}ùøº’iUGabSW"S·aSP«×ê¯W×½²üÄëÊÔÚ´^­º–+>¡žT?ŸœœU—ÿ¯VÏe¬ž×ëg³Ù§Ù©_[»¼¼¬ú§«¥!ªq<ÙwcËÕˍå›|åšÓÊÍÊ+óo®òW–Žc ‰óÍQþ³Sv]!ëê/1ÌÖ^«l{ïÿïü õ1Ä´²zb)=‘¨&•›“«ê[û‹íÀØrÈ}Š#;Ý*øìòäâs1áß žL·oûs­V;?Lú`Š³>D5Ðœ
5³¡a„(A¨ÊÕ¦£­gî1‚]ÒÇBš½Å'"=ŽUsˆÞ:k{€ùw(Øõb?—·£­«cçlËŽrgìÕþºø³€Ü]©rzy~°T$”Ÿ,^lé©í¥öwæˆËÀb²h-&;ðì0á?“!‰ÚŒ¶)j[:b™m¢Ìµ™Ô¹ôZQé
ÄçÒ²ú­_Z"´¨wìýä@ß´Í $„¢–¦¶¨öÑæ¶K%t,‘Ò~"ÂÅʶüøÊv=ÎÑqûªÄû×îå™–˜ÀïñžFK~n¡ÞLš2œÜ#4¶ ÞaÔՏeÜ%#ˆ"ˆn…#a °f¦5ÊJ–û;ÀL‡‡Kì•{L#a·UÎb)DQOh1„kƒT„´£À¬Ð›àYBùoIÖ:M˜=‰ßÀQñð¨FD’ž½šŒÎUû(-_O+™ÅåÉ”ï.:š m
éª;SÒq˜ÒáóDc¦|,8¤ºÕbÆä·-W¾ïˆÂjËy8IÞÄ$jSÜ#Ãs€Í6ِ~Öˆ•Ð‹}D2ž(òîÀbÚC;´.ßþ|Ã=‘‚niL¶î¼„hi›ï U`b¡z™
m&Þ³§€"1Ä2@ÓQ¦ŒkwK§cAšÊÅ£¡ü¢¸)ÿPnñíß™±ñxA5ÌSl§÷BeB6&2¸m ^`8%œU"–å[äÄ•8ò6ŸQ¸ZÈKƒDHÙ©é•jeÅÎÏ9âl+pl‰4ʯƒã̹íÇrdÓUM‰†ƒÝ.¡Õ%ÿ’T²À¬h:›ip5©;ú×tU‡Ã Ž£‚&-ÄWWàùN*J[$[Âß8âˆhOj CZ¨XˆC^ÚÔc¸1¢KOßL©)?&l¥VÔ9öЊÐ#XãCa&\¤ánNŽSBv@D,èÞ<¡Ž\5»•«˹acÑ’‡´Ÿ{$OWFkÆÍ ¡›Y7ìÀ Èù6œÚ<òôÀ±ÕÀZmH£Ë%¢3Q¨¡kãJ´}6µ§‰”8ó)LÔ*†
¾UgÕ|¿xW‘+¢o/š %Ã;×õÊ ^}kº9Ò“iÊãÃ|üŸk ¿Ã¤øÍf¤‰ÊÄѯwÕV*¬ »÷'ÐÇÙw ŽF„Ä›>ˉ‰ðâ2=nH<
8]ŠR×¥£w‘Ö2Ì$W÷Ó§Sê#nZä9híââô¬vàÝAEÔ§‡Š¥ê4eœfÝ»­®Oš–j*t¾ŽóL™æt0!üTÊ?¨â…ëjN´î˜TÈ”=u7<ËÈ&ÛÄM(e§¦MôÁpÔ<u¥GÜ/Þ3ÔÔ“Ò©,óˆaÿ÷ÂN„ˆ5ýØå=BZäÚô´mU ù*h¥¤öî’Ô.\%sP¾1h««†q]H0x c‘IŽu€“BÔ‹C×’²µm\
›ÞU~Å«¤C¥J
B§ö]=‡¶Wã'ƒÌj(nG~Üÿ¸ŒáÉ oC- sV{ò¼÷0•DƒÈË;g?z ŒÚ°M!3í¯/V4Óó8º 7¿]Frá³#摳O#Bž¾j6Síf ëV‘F³‘u„Š”YQªÀÿÇÑhÇÆ1÷îxì"„wèÖ¤”ŠU†™¹S‘¢6‡g(æû'÷IDB¨Âc‡üoDg×\£î³aì{ÀWtˆ(:ßÝì¾â>pîåu ûu.xF3|f²:nî„Ë—9Æ^¼Gÿõ53“ÿ=: ˜¢¤øå:Š.Ç ZA$ƒZ0g —&%üà’ïG1l‘”o¾?ìpí¿î{gئ…å»A<g2·Ä¼Ð'LyÊ2ßí{-ž^苝Ÿ´Uß| ^ÝõéþÍPKÚþ/i×  ü/  PK  ÅHxQ               content.xml½WMnã6Þ÷‚
A †Q<&jìÙƒHŠ¢NvUÐ$%¥D•¤,{7Çhw]Îœav“›ÌIúHYŽåhê¢@àX|ßûï}ûj›É`õ*Ÿ‡ÑåUðœ*&òtþüð½ _->»UI"(™¢eÆs‹¨Ê-ü@;7qÆ-™‡¥ÎcEŒ0qN2nbKcUð¼Ñ‰;lìýÔϵå©Úû8zú‰šª»5%

bÅJÌ(vÖÖ1ÆN·vt©tŠ¯¯®^àú¹Ao¥ÈoñUU]V3nnn°—6PF[\QjéQŒb.¹ Íàè2Â
Ö؝œ\
î§`ùÖNUvؾ.Ó¤šªë°0Cõ›®>c}]³I'§¼IGÚG×DONÞƒûÚº°'šÿ5Ö¼PÚ¶u&«é]òྯ¼ÌV\O.±äI£aV«“ÃZia¹îÁéI8%’vë8}!¦ëAQN/Ñ
ö ¶e൛X¶ä’¨2‡¼öþù¶àZ8‘^-X8œã“QDWØa¼Tÿ"„= õ, IpÙ,Cëý¨¥Pf &Õªˆ{Ú}s±ë¦y‰ïAè?îï:>ÔÙÔ:ì`©Åä5ªÑƒê«ìX¨Ðûñ£¼–D{3¢pkq 6lÔô/÷wKºæéÀây0ÞX’w¤îüm§5Î%£XrØ»ƒrn×6“ão 'm ©fì(bžaxc  àÕçíú3³Ç4~ÂN†Åãn­]2Ïígó’Û§Þ»ÌÂEs¨Ûnp{À] %„rÄ8•fq[V{ÔÏ®ó𮤂‘`Ir…zƒË„ÜÍÃ/H¡Ì7=P}›‹RžCK€ÙL%Œ ñ3~°®ßè` jɸïà„ ´ÊH>@ÂRØÚ
ÑÂSÞ'9OŠíSjsNh]+þ«víŒåÙ91Ý ª•Q‰
~%ßq1×î‰í‡¥È–e~$¦Nr®<¶xûsRZ˜H+(òvڍôŸƒhŒZ_û( ¢IªI±npà.üþÕZK MF4 ÃŽjPDȵÜ-ÛÄ@ ÀÛÀ»tÅ¢aOÒ:B—`/Þ.ݧií+Åv탋eqëï·†ÿQ™¶<OÄ„)$Ù!UZ¸¹s$á=d <îÅuÒßKY[oŸ‹ñ,cM+ϳ_Ï6òm}›?ÛÎk‘–ºÏñâµF˜`ÜؽZqùøîÃßÞ_||óçÅã[ôøö7ø_bôÕ$u|Úx’®“µ¶»oþº@A<˜,<:<òÃxñPK…ÕçáР Y  PK    ÅHxQòª@Aâ  â     Thumbnails/thumbnail.png‰PNG

   
IHDR   µ      ÂýÇé   PLTEYbkd\Ywyty}vˆv‚‹}“ªŽŽ…Ž˜–‘Œœ‘‡™”Ž————–›œ–•‰“¨œ¤ž žž¤¬–¡±Ÿ¦³ª“¬¦—¨¡Ÿ¤£¤¢¥ª©§¦ª«©³©¦´®ª²³µ´¹¹½½½«µÁ©·É¯¾ÉºÃÁ¿ÄɶÊÜ»ÑæÁ¬£Ãº®Â¿¼É¿±Ó¿­Â¿ÊÁµÓɵÄÃÃÂÅÊÊÆÀÌÍÍÁË×ÏÔÙÑÆÁÑÌÆÓÓÓÞÙÒÚÚÜÁÑáÎ×áÉÙçÐáìÞïñäÔÉìÙÃâÜÖäßÞæáÜòéÞÿéÓãääáæìäéïïéäíííìñöîôúëúÿüòåùôïÿùïñññôùÿüöñÿúõþÿþ   ÿÿÿ3lÌI  ’IDATxÚíÕÉJQÐvžgƒŠcˆ8Ä€‰­’ç)NQ1±þÿSŒ[wn4
çnê-[TyLBMMMMMMMMMMMý#×Cµˆ·fÞþz¦’ônçM=v\Ú]ØÖë¿Pwjiõ¶Q‹»ÓˆjD=[º‰htµº’¼ìË•dsd Þz¶b1›MêãÍnV_–"ËŠ±Ü™å£x_jÅêKœD|t¯O¢ýПåZo4m#5õÿ¨³¸iµ«­ïgûñ9'ê«áÅݹÉÂÜza>­¯œåD}?1½·6µ¿6X9ïoí\Ôò¡~*ôÓjZ/?otnú¡m¤¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦þe¾ K?¼)á–Ý9    IEND®B`‚PK  ÅHxQ               META-INF/manifest.xml­“MjÃ0F÷9…ѶXJÛMq²(ôéT{ä H#¡ŸÜ¾²‰—ˆ!;É¿÷ÍØÚìNÖTG5앯YÔº©oØ÷þ«þ`»íjc¡†˜ä´¨Ê{¯Û†å@Ò©ˆQ’²ej¥ó@k³Jòo½M×Ý,À;» ƒÓÄ
½œ@ÚeêT*Õœ<Ž”‘NklAΣi»ªn-h4P—òp¾ÐÙ˜Ú«th˜¸›ë6èPÕéì¡aÊ{ƒíH©ãã ø¼užJ &–døt¤±ÏaÄÆ7ñ ;fâ¥už‘·sÂ2ùôŒ‡N? .U/EºÌÓÙ@ÂÞ1 3‹±’z:4BJå:<?mùFiø?žÍݲý!…&Š4-¹§þŽ­êA çŲÿ®úöPKT´O.  %  PK     ÅHxQ^Æ2 '   '                    mimetypePK     ÅHxQ                         M   Configurations2/progressbar/PK     ÅHxQ                         ‡   Configurations2/menubar/PK     ÅHxQ                         ½   Configurations2/popupmenu/PK     ÅHxQ                         õ   Configurations2/statusbar/PK     ÅHxQ                         -  Configurations2/toolbar/PK     ÅHxQ                         c  Configurations2/accelerator/PK     ÅHxQ                           Configurations2/floater/PK     ÅHxQ                         Ó  Configurations2/toolpanel/PK     ÅHxQ                            Configurations2/images/Bitmaps/PK   ÅHxQ´÷hÒ  ƒ               H  manifest.rdfPK   ÅHxQçc±  J- 
             ‡  styles.xmlPK   ÅHxQ×%®úÏ  ë               Ï   meta.xmlPK   ÅHxQÚþ/i×  ü/               Ô
  settings.xmlPK   ÅHxQ…ÕçáР Y               å  content.xmlPK     ÅHxQòª@Aâ  â               î  Thumbnails/thumbnail.pngPK   ÅHxQT´O.  %                 META-INF/manifest.xmlPK      e  w   

(ce que vous voyez ci-dessus n'est pas exact et est converti par le php du forum)

Sinon il me semble qu'il y a possibilité d'enregistrer ou de convertir un odt en pure xml, à réfléchir :)

6
Vos projets et Montages d'Électronique / Les livres de sauvegarde
« le: novembre 21, 2020, 06:14:36 pm »
Bonjour ;)

Je me permets de partager avec vous une idée que j'ai titré "Les livres de sauvegarde" :

Citer
Face à l'obsolescence progressive, mais bien réelle, des systèmes analogiques et numériques dans le paysage informatique complexe actuel (multitude de technologies matérielles et logicielles plus ou moins hétérogènes), nul ne sait si un matériel de sauvegarde standard considéré de nos jours pourra encore être lu (ouvert en lecture) dans les décennies à venir, et ce malgré le soin apporté à la propagation dans le temps des normes de standardisation de l'analogique et du numérique dans leur ensemble.

Le support imprimé comme le papier relié sous la forme d'un livre peut, dans de bonnes conditions de conservation, rester lisible après plusieurs siècles, voir millénaires. Contrairement aux mémoires non volatiles analogiques ou numériques qui peuvent faire office de supports de sauvegarde (rubans perforés, bandes magnétiques, mémoires à base de semi-conducteurs, etc...), la lecture du papier imprimé s'affranchit d'utiliser un matériel spécifique pour être compréhensible ou décodable, ce qui en fait un candidat relativement pérenne afin d'archiver et de transmettre des informations aux générations futures, en considération de la dépréciation et de l'évolution continue et accélérée respectivement des anciennes et des nouvelles technologies. De surcroît, la grande accessibilité du livre en lecture/écriture est fonction des caractéristiques rudimentaires propres aux techniques de l'imprimerie. La rusticité du support d'impression et de fait, son fonctionnement et sa mise en œuvre minimaliste (sans source d'énergie et dépourvu de composants complexes), participent grandement à sa relative robustesse eu égard les aléas et la sensibilité électromagnétique à l'environnement extérieur des technologies de rétention informatiques analogiques et numériques conventionnelles.

C'est pourquoi je pense être utile l'existence de ce présent dispositif particulièrement dans des contextes critiques, c'est-à-dire en cas d'obsolescence des techniques informatiques dites modernes à l'échéance de périodes dépréciatives et évolutives, de crash d'un ou de plusieurs systèmes redondants à différents lieux géographiques, de suppression intentionnelle de données à l'aide des techniques de piratage sur des machines particulières ou des serveurs connectés à internet, ceci conjointement à des situations éventuelles de crises systémiques, de conflits armés de types multiples, ou plus largement d'effondrement civilisationnel favorisant la dispersion et l'élimination d'informations importantes.




Le contenu de chacun de mes livres a pour origine un seul fichier PDF généré automatiquement via une routine que j'ai développé. En effet cette routine explore l'arborescence de fichiers que vous souhaitez sauvegarder, en extrait le contenu UTF-8, et compile le tout en un fichier PDF que vous pouvez directement envoyer à un imprimeur (voir plus bas).



Cette routine (pour le système d'exploitation Linux que j'utilise) permet de générer automatiquement le contenu d'un livre complet sous la forme d'un seul fichier PDF via une arborescence de fichiers (organisation hiérarchique des fichiers dans des répertoires) dont le contenu UTF-8 est extrait :
Citer
C'est le contenu UTF-8 (pour "Unicode Transformation Format 8" ou format de transformation Unicode sur 8 bits) de vos fichiers à sauvegarder qui est utilisé afin de générer un fichier unique PDF imprimable (book content.pdf), contenu prenant ainsi la forme de caractères normalisés qui peut être issu de divers langages, soit par exemple du binaire, de l'hexadécimal, du C++, ou tout autre caractère UTF-8 imprimable. Attention cependant, si des caractères dans vos fichiers ne font pas partie de la norme UTF-8, il ne pourront pas être traités correctement.

Ainsi ce que je propose ici est un outil qui, bien utilisé, vous permettra de sauvegarder vos fichiers sur des supports imprimés (livres, documents divers), via la simple génération d'un seul fichier .pdf (pour "Portable Document Format" ou format de document portable), un format de fichier pris en charge par tous les imprimeurs.

Ma routine d'automatisation prend donc en entrée une arborescence de fichiers, elle permet de choisir les dimensions des pages du livre, les dimensions des marges générales, la dimension de la marge de reliure qui servira à positionner le texte en retrait par rapport à la reliure du livre (ceci afin de faciliter l'ergonomie de lecture), la taille des caractères du texte qui sera imprimé, la police de caractère utilisée, et les dimensions du fond perdu (soit la marge qui sera rognée par la machine de coupe). Si besoin, il est possible également de trier manuellement l'ordre d'apparition des fichiers dans le livre, ce qui peut être intéressant si le tri alphanumérique par défaut n'est pas souhaité.

Une fois ces choix effectués, un fichier nommé book content.pdf est créé. Ce fichier répertorie tout le contenu des fichiers de l'arborescence, avec la pagination, la numérotation des lignes, la numérotation des pages (paires et impaires), et la table des fichiers en toute fin du livre. Ci dessous, la routine (.sh) permettant la création automatique du contenu d'un livre PDF (.pdf) à partir d'une arborescence de fichiers :

#!/bin/bash

echo "Page width in mm ?"
read widthPage

echo -e "\nPage height in mm ?"
read heightPage

echo -e "\nPage margin in mm ?"
read marginPage

echo -e "\nGutter margin in mm ?"
read marginGutter

echo -e "\nFont size in mm ?"
read fontSize

echo -e "\nFont name ?"
read fontName

echo -e "\nCutter margin in mm ?"
read marginCutter

echo ""

next=false

while [ $next == false ]
do
echo "Sort option ?"
echo "a = Alphanumeric sort"
echo "m = Manual sort"

read menuOptionSort

if [ $menuOptionSort == "a" ] || [ $menuOptionSort == "m" ]
then
next=true
fi

clear
done

rm tmp -r -f
rm "book content.pdf" -f

nameBash=$(basename "$0")
nameLink=$(basename "$1")
countTable=0

shopt -s globstar

for file in **/*
do
if [ -f "$file" ] && [ "$file" != "$nameBash" ] && [ "$file" != "$nameLink" ]
then
fileTable[countTable]=$file
((countTable++))
fi
done

if [ $countTable == 0 ]
then
echo "No file detected"
else
iterationTable=0

if [ $menuOptionSort == "m" ]
then
next=false

while [ $next == false ]
do
echo "Manual sort :"
echo "e = Exit"
echo "s = Save file tree (file.tree)"
echo "l = Load file tree (file.tree)"
echo "d = Delete file tree (file.tree)"
echo ""
echo "File tree :"

for ((iterationTableDisplay=0; iterationTableDisplay < countTable; iterationTableDisplay++))
do
if [ $iterationTableDisplay == $iterationTable ]
then
echo $((iterationTableDisplay+1))" = "${fileTable[iterationTableDisplay]}" <"
else
echo $((iterationTableDisplay+1))" = "${fileTable[iterationTableDisplay]}
fi
done

read menuManualSort

if [ $menuManualSort == "e" ]
then
next=true
elif [ $menuManualSort == "s" ]
then
rm file.tree -f

for ((iterationTableForWriting=0; iterationTableForWriting < countTable; iterationTableForWriting++))
do
echo ${fileTable[iterationTableForWriting]} >> file.tree
done
elif [ $menuManualSort == "l" ]
then
countTable=0

while read line
do
fileTable[$countTable]=$line
((countTable++))
done < file.tree
elif [ $menuManualSort == "d" ]
then
rm file.tree -f
elif (($menuManualSort >= 1 && $menuManualSort <= $countTable))
then
saveTable=${fileTable[$iterationTable]}

fileTable[$iterationTable]=${fileTable[$((menuManualSort-1))]}
fileTable[$((menuManualSort-1))]=$saveTable
fi

clear

if (($iterationTable == $countTable - 1))
then
iterationTable=0
else
((iterationTable++))
fi
done
fi

echo "Progress = 0.0%"

rm tmp -r -f
mkdir tmp

bashString="__BASH_"
countLineTotal=0

characterMeasure=""

for ((iterationCharacter=0; iterationCharacter < 1000; iterationCharacter++))
do
characterMeasure=$characterMeasure"_"
done

ratioFontSize=$(inkscape --without-gui -W <(echo "<svg><text font-family=\""$fontName"\" font-size=\""$fontSize"\">"$characterMeasure"</text></svg>") 2>/dev/null)
countCharacterPerLine=$(echo "("$widthPage"-(("$marginPage"*2)+"$marginGutter"))/("$ratioFontSize"/1000)" | bc -l)
countCharacterPerLineDisplay=$(echo "scale=0;("$countCharacterPerLine"*10)/10" | bc -l)

countLinePerPage=$(echo "("$heightPage"-(("$marginPage"*2)+("$fontSize"/3)))/"$fontSize | bc -l)
countLinePerPageDisplay=$(echo "scale=0;("$countLinePerPage"*10)/10" | bc -l)

for ((iterationTable=0; iterationTable < countTable; iterationTable++))
do
clear

progress=$(echo "25/("$countTable"/("$iterationTable"+1))" | bc -l)
progressDisplay=$(echo "scale=1;(("$progress"+0.05)*10)/10" | bc -l)

if ((${#progressDisplay} == 2))
then
echo "Progress = 0"$progressDisplay"%"
else
echo "Progress = "$progressDisplay"%"
fi

sizeRaw=$(stat -c "%s" "${fileTable[iterationTable]}")

if [ $sizeRaw == 0 ]
then
size="(0 octet)"
elif [ $sizeRaw == 1 ]
then
size="(1 octet)"
elif (($sizeRaw < 1024))
then
size="("$sizeRaw" octets)"
elif (($sizeRaw < 1048576))
then
sizeInteger=$((sizeRaw/1024))
sizeDecimal=$(echo "("$sizeRaw"/1024)-"$((sizeRaw/1024)) | bc -l)
sizeDecimalDisplay=$(echo "scale=1;("$sizeDecimal"*10)/10" | bc -l)
sizeNumber=$(echo $sizeRaw"/1024" | bc -l)
sizeNumberDisplay=$(echo "scale=1;("$sizeNumber"*10)/10" | bc -l)

if [ $sizeDecimalDisplay == 0 ]
then
if (($(echo $sizeNumberDisplay" == "$sizeNumber | bc -l)))
then
size="("$sizeRaw" octets = "$sizeInteger"Kio)"
else
size="("$sizeRaw" octets ≈ "$sizeInteger"Kio)"
fi
else
if (($(echo $sizeNumberDisplay" == "$sizeNumber | bc -l)))
then
size="("$sizeRaw" octets = "$sizeNumberDisplay"Kio)"
else
size="("$sizeRaw" octets ≈ "$sizeNumberDisplay"Kio)"
fi
fi
elif (($sizeRaw < 1073741824))
then
sizeInteger=$((sizeRaw/1048576))
sizeDecimal=$(echo "("$sizeRaw"/1048576)-"$((sizeRaw/1048576)) | bc -l)
sizeDecimalDisplay=$(echo "scale=1;("$sizeDecimal"*10)/10" | bc -l)
sizeNumber=$(echo $sizeRaw"/1048576" | bc -l)
sizeNumberDisplay=$(echo "scale=1;("$sizeNumber"*10)/10" | bc -l)

if [ $sizeDecimalDisplay == 0 ]
then
if (($(echo $sizeNumberDisplay" == "$sizeNumber | bc -l)))
then
size="("$sizeRaw" octets = "$sizeInteger"Mio)"
else
size="("$sizeRaw" octets ≈ "$sizeInteger"Mio)"
fi
else
if (($(echo $sizeNumberDisplay" == "$sizeNumber | bc -l)))
then
size="("$sizeRaw" octets = "$sizeNumberDisplay"Mio)"
else
size="("$sizeRaw" octets ≈ "$sizeNumberDisplay"Mio)"
fi
fi
fi

echo -e "Fichier "${fileTable[iterationTable]}" "$size"\u00a0:\n" | fold -s -w$countCharacterPerLineDisplay >> tmp/tmp3

cp "${fileTable[iterationTable]}" tmp/tmp2
sed -i tmp/tmp2 -e "s/ /"$bashString"SPACE/g" -e "s/\t/"$bashString"TABULATION/g" -e "s/*/"$bashString"STAR/g" -e "s/\\\/"$bashString"BACKSLASH/g"

countTmpLine=$(wc -l < tmp/tmp2)
iterationTmpLine=1

while read line
do
spacePrefixLine=""

for ((iterationSpace=0; iterationSpace < ${#countTmpLine} - ${#iterationTmpLine}; iterationSpace++))
do
spacePrefixLine=$spacePrefixLine$bashString"SPACE"
done

spacePrefixSubline=""

for ((iterationSpace=0; iterationSpace < ${#countTmpLine}; iterationSpace++))
do
spacePrefixSubline=$spacePrefixSubline$bashString"SPACE"
done

echo $line | sed -e "s/"$bashString"SPACE/ /g" -e "s/"$bashString"TABULATION/   /g" -e "s/"$bashString"STAR/*/g" -e "s/"$bashString"BACKSLASH/\\\/g" | fold -s -w$((countCharacterPerLineDisplay-(${#countTmpLine}+3))) | sed -e "s/ /"$bashString"SPACE/g" -e "s/*/"$bashString"STAR/g" -e "s/\\\/"$bashString"BACKSLASH/g" > tmp/tmp1

iterationTmpSubline=1

while read subline
do
if [ $iterationTmpSubline == 1 ]
then
echo $spacePrefixLine$iterationTmpLine" : "$subline | sed -e "s/"$bashString"SPACE/ /g" -e "s/"$bashString"STAR/*/g" -e "s/"$bashString"BACKSLASH/\\\/g" >> tmp/tmp3
else
echo $spacePrefixSubline" : "$subline | sed -e "s/"$bashString"SPACE/ /g" -e "s/"$bashString"STAR/*/g" -e "s/"$bashString"BACKSLASH/\\\/g" >> tmp/tmp3
fi

((iterationTmpSubline++))
done < tmp/tmp1

((iterationTmpLine++))
done < tmp/tmp2

countLine=$(wc -l < tmp/tmp3)
iterationLinePerPage=0
fillPage=$((countLinePerPageDisplay-2))

for ((iterationLine=0; iterationLine < countLine - 1; iterationLine++))
do
if (($iterationLinePerPage == $countLinePerPageDisplay - 3))
then
fillPage=$((fillPage+(countLinePerPageDisplay-2)))
iterationLinePerPage=0
else
((iterationLinePerPage++))
fi
done

for ((iterationLine=0; iterationLine < fillPage - countLine; iterationLine++))
do
echo "" >> tmp/tmp3
done

titlePageTable[iterationTable]=${fileTable[iterationTable]}

if [ $countLineTotal == 0 ]
then
numberPageTable[iterationTable]=1
else
numberPageTable[iterationTable]=$(((countLineTotal/(countLinePerPageDisplay-2))+1))
fi

countLineTotal=$(wc -l < tmp/tmp3)
done

iterationLinePerPage=0
numberPageContent=1
flipFlop=false

for ((iterationLine=0; iterationLine < countLineTotal; iterationLine++))
do
if (($iterationLinePerPage == $countLinePerPageDisplay - 1))
then
sed -i tmp/tmp3 -e $iterationLine"i\\\\"

if [ $flipFlop == false ]
then
lenghtNumberPageContent=${#numberPageContent}
fillSpace=""

for ((iterationCharacter=0; iterationCharacter < countCharacterPerLineDisplay - lenghtNumberPageContent; iterationCharacter++))
do
fillSpace=$fillSpace$bashString"SPACE"
done

sed -i tmp/tmp3 -e $((iterationLine+1))"i"$fillSpace$numberPageContent | sed -e "s/"$bashString"SPACE/ /g"

flipFlop=true
else
sed -i tmp/tmp3 -e $((iterationLine+1))"i"$numberPageContent
flipFlop=false
fi

iterationLinePerPage=0

((numberPageContent++))

clear

progress=$(echo "25+(25/("$countLineTotal"/("$iterationLine"+1)))" | bc -l)
progressDisplay=$(echo "scale=1;(("$progress"+0.05)*10)/10" | bc -l)

echo "Progress = "$progressDisplay"%"
else
((iterationLinePerPage++))
fi

countLineTotal=$(wc -l < tmp/tmp3)
done

if [ $flipFlop == false ]
then
lenghtNumberPageContent=${#numberPageContent}
fillSpace=""

for ((iterationCharacter=0; iterationCharacter < countCharacterPerLineDisplay - lenghtNumberPageContent; iterationCharacter++))
do
fillSpace=$fillSpace$bashString"SPACE"
done

echo -e "\n"$fillSpace$numberPageContent | sed -e "s/"$bashString"SPACE/ /g" >> tmp/tmp3
else
echo -e "\n"$numberPageContent >> tmp/tmp3
fi

echo -e "Table des fichiers\u00a0:\n" | fold -s -w$countCharacterPerLineDisplay >> tmp/tmp3

lenghtMaxPageNumber=${#numberPageTable[$((countTable-1))]}
lenghtMaxPageTitle=$(((countCharacterPerLineDisplay-3)-${#numberPageTable[$((countTable-1))]}))

for ((iterationTable=0; iterationTable < countTable; iterationTable++))
do
echo ${titlePageTable[$iterationTable]} | fold -s -w$lenghtMaxPageTitle > tmp/tmp4

countTmpLine=$(wc -l < tmp/tmp4)

iterationTmpLine=1
point="."

while read line
do
if [ $iterationTmpLine != $countTmpLine ]
then
echo $line >> tmp/tmp3
else
lenghtLastLine=$((${#line}+${#numberPageTable[iterationTable]}))

for ((iterationCharacter=0; iterationCharacter < countCharacterPerLineDisplay - (lenghtLastLine + 3); iterationCharacter++))
do
point=$point"."
done

echo $line" "$point" "${numberPageTable[iterationTable]} >> tmp/tmp3
fi

((iterationTmpLine++))
done < tmp/tmp4
done

countLineTotal=$(wc -l < tmp/tmp3)
iterationLinePerPage=0
fillPage=$countLinePerPageDisplay

for ((iterationLine=0; iterationLine < countLineTotal - 1; iterationLine++))
do
if (($iterationLinePerPage == $countLinePerPageDisplay - 1))
then
fillPage=$((fillPage+countLinePerPageDisplay))
iterationLinePerPage=0
else
((iterationLinePerPage++))
fi
done

for ((iterationLine=0; iterationLine < fillPage - countLineTotal; iterationLine++))
do
echo "" >> tmp/tmp3
done

cp tmp/tmp3 tmp/tmp5

sed -i tmp/tmp5 -e "s/ /_/g" -e "s/*/_/g" -e "s/\\\/_/g"

iterationLine=0

while read line
do
lenghtLineContent[iterationLine]=${#line}
((iterationLine++))
done < tmp/tmp5

countLineTotal=$(wc -l < tmp/tmp3)
iterationLine=0
iterationLineDisplayed=0

cp tmp/tmp3 tmp/tmp6

sed -i tmp/tmp6 -e "s/ /"$bashString"SPACE/g" -e "s/*/"$bashString"STAR/g" -e "s/\\\/"$bashString"BACKSLASH/g"

clear

echo "Progress = 50.0%"

while read line
do
fillSpace=""

for ((iterationCharacter=0; iterationCharacter < countCharacterPerLineDisplay - lenghtLineContent[iterationLine]; iterationCharacter++))
do
fillSpace=$fillSpace$bashString"SPACE"
done

echo $line$fillSpace | sed -e "s/"$bashString"SPACE/ /g" -e "s/"$bashString"STAR/*/g" -e "s/"$bashString"BACKSLASH/\\\/g" >> tmp/tmp7

((iterationLine++))

if (($iterationLineDisplayed == $countLinePerPageDisplay - 1))
then
clear

progress=$(echo "50+(25/("$countLineTotal"/"$iterationLine"))" | bc -l)
progressDisplay=$(echo "scale=1;(("$progress"+0.05)*10)/10" | bc -l)

echo "Progress = "$progressDisplay"%"

iterationLineDisplayed=0
else
((iterationLineDisplayed++))
fi
done < tmp/tmp6

iterationLine=0
iterationFileDisplayed=0
firstPage=false
flipFlop=false
countPageTotal=$(($(wc -l < tmp/tmp3)/countLinePerPageDisplay))

sed -i tmp/tmp7 -e "s/ /"$bashString"SPACE/g" -e "s/*/"$bashString"STAR/g" -e "s/\\\/"$bashString"BACKSLASH/g"

while read line
do
if [ $iterationLine == 0 ]
then
echo "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\"?>" > tmp/tmp.svg
echo "<svg width=\""$(echo "("$marginCutter"*2)+"$widthPage | bc -l)"mm\" height=\""$(echo "("$marginCutter"*2)+"$heightPage | bc -l)"mm\">" >> tmp/tmp.svg
fi

if [ $flipFlop == false ]
then
echo "<text x=\""$(echo $marginCutter"+("$widthPage"-"$marginPage")" | bc -l)"mm\" y=\""$(echo $marginCutter"+("$marginPage"+("$fontSize"*("$iterationLine"+1)))" | bc -l)"mm\" text-anchor=\"end\" font-family=\""$fontName"\" font-size=\""$fontSize"mm\" fill=\"#000000\" xml:space=\"preserve\">"$(echo $line | sed -e "s/&/&amp;/g" -e "s/</\&lt;/g" -e "s/>/\&gt;/g" -e "s/\"/\&quot;/g" -e "s/'/\&apos;/g")"</text>" | sed -e "s/"$bashString"SPACE/ /g" -e "s/"$bashString"STAR/*/g" -e "s/"$bashString"BACKSLASH/\\\/g" >> tmp/tmp.svg
else
echo "<text x=\""$(echo $marginCutter"+"$marginPage | bc -l)"mm\" y=\""$(echo $marginCutter"+("$marginPage"+("$fontSize"*("$iterationLine"+1)))" | bc -l)"mm\" text-anchor=\"start\" font-family=\""$fontName"\" font-size=\""$fontSize"mm\" fill=\"#000000\" xml:space=\"preserve\">"$(echo $line | sed -e "s/&/&amp;/g" -e "s/</\&lt;/g" -e "s/>/\&gt;/g" -e "s/\"/\&quot;/g" -e "s/'/\&apos;/g")"</text>" | sed -e "s/"$bashString"SPACE/ /g" -e "s/"$bashString"STAR/*/g" -e "s/"$bashString"BACKSLASH/\\\/g" >> tmp/tmp.svg
fi

if (($iterationLine == $countLinePerPageDisplay - 1))
then
echo "<rect x=\"0mm\" y=\"0mm\" width=\""$(echo "("$marginCutter"*2)+"$widthPage | bc -l)"mm\" height=\""$(echo $marginCutter"+"$marginPage | bc -l)"mm\" fill=\"#ffffff\"/>" >> tmp/tmp.svg
echo "<rect x=\"0mm\" y=\""$(echo $marginCutter"+("$heightPage"-"$marginPage")" | bc -l)"mm\" width=\""$(echo "("$marginCutter"*2)+"$widthPage | bc -l)"mm\" height=\""$(echo $marginCutter"+"$marginPage | bc -l)"mm\" fill=\"#ffffff\"/>" >> tmp/tmp.svg
echo "<rect x=\"0mm\" y=\""$(echo $marginCutter"+"$marginPage | bc -l)"mm\" width=\""$(echo $marginCutter"+"$marginPage | bc -l)"mm\" height=\""$(echo $heightPage"-("$marginPage"*2)" | bc -l)"mm\" fill=\"#ffffff\"/>" >> tmp/tmp.svg
echo "<rect x=\""$(echo $marginCutter"+("$widthPage"-"$marginPage")" | bc -l)"mm\" y=\""$(echo $marginCutter"+"$marginPage | bc -l)"mm\" width=\""$(echo $marginCutter"+"$marginPage | bc -l)"mm\" height=\""$(echo $heightPage"-("$marginPage"*2)" | bc -l)"mm\" fill=\"#ffffff\"/>" >> tmp/tmp.svg

echo "</svg>" >> tmp/tmp.svg

if [ $firstPage == false ]
then
rsvg-convert -f pdf -d 72 -p 72 tmp/tmp.svg -o tmp/tmp1.pdf
firstPage=true
else
rsvg-convert -f pdf -d 72 -p 72 tmp/tmp.svg -o tmp/tmp2.pdf
pdftk tmp/tmp1.pdf tmp/tmp2.pdf cat output tmp/tmp3.pdf

mv tmp/tmp3.pdf tmp/tmp1.pdf
fi

if [ $flipFlop == false ]
then
flipFlop=true
else
flipFlop=false
fi

iterationLine=0

((iterationFileDisplayed++))

clear

progress=$(echo "75+(25/("$countPageTotal"/"$iterationFileDisplayed"))" | bc -l)
progressDisplay=$(echo "scale=1;(("$progress"+0.05)*10)/10" | bc -l)

echo "Progress = "$progressDisplay"%"
else
((iterationLine++))
fi
done < tmp/tmp7

exiftool -q -m -all= tmp/tmp1.pdf

mv tmp/tmp1.pdf "book content.pdf"
rm tmp -r -f

lenghtTotalCover=$(echo "(("$marginCutter"*2)+("$widthPage"*2))+("$countPageTotal"*0.06)" | bc -l)
widthFrontBackCover=$(echo $marginCutter"+"$widthPage | bc -l)
heightFrontBackCover=$(echo "("$marginCutter"*2)+"$heightPage | bc -l)
widthSideCover=$(echo "("$countPageTotal"*0.06)" | bc -l)

lenghtTotalCoverDisplay=$(echo "scale=3;(("$lenghtTotalCover"+0.0005)*10)/10" | bc -l)
widthFrontBackCoverDisplay=$(echo "scale=3;(("$widthFrontBackCover"+0.0005)*10)/10" | bc -l)
heightFrontBackCoverDisplay=$(echo "scale=3;(("$heightFrontBackCover"+0.0005)*10)/10" | bc -l)
widthSideCoverDisplay=$(echo "scale=3;(("$widthSideCover"+0.0005)*10)/10" | bc -l)

sizeRaw=0

for ((iterationTable=0; iterationTable < countTable; iterationTable++))
do
sizeRaw=$((sizeRaw+$(stat -c "%s" "${fileTable[iterationTable]}")))
done

if [ $sizeRaw == 0 ]
then
size="0 byte"
elif [ $sizeRaw == 1 ]
then
size="1 byte"
elif (($sizeRaw < 1024))
then
size=$sizeRaw" bytes"
elif (($sizeRaw < 1048576))
then
sizeInteger=$((sizeRaw/1024))
sizeDecimal=$(echo "("$sizeRaw"/1024)-"$((sizeRaw/1024)) | bc -l)
sizeDecimalDisplay=$(echo "scale=1;("$sizeDecimal"*10)/10" | bc -l)
sizeNumber=$(echo $sizeRaw"/1024" | bc -l)
sizeNumberDisplay=$(echo "scale=1;("$sizeNumber"*10)/10" | bc -l)

if [ $sizeDecimalDisplay == 0 ]
then
if (($(echo $sizeNumberDisplay" == "$sizeNumber | bc -l)))
then
size=$sizeRaw" bytes ("$sizeInteger"KiB)"
else
size=$sizeRaw" bytes (≈ "$sizeInteger"KiB)"
fi
else
if (($(echo $sizeNumberDisplay" == "$sizeNumber | bc -l)))
then
size=$sizeRaw" bytes ("$sizeNumberDisplay"KiB)"
else
size=$sizeRaw" bytes (≈ "$sizeNumberDisplay"KiB)"
fi
fi
elif (($sizeRaw < 1073741824))
then
sizeInteger=$((sizeRaw/1048576))
sizeDecimal=$(echo "("$sizeRaw"/1048576)-"$((sizeRaw/1048576)) | bc -l)
sizeDecimalDisplay=$(echo "scale=1;("$sizeDecimal"*10)/10" | bc -l)
sizeNumber=$(echo $sizeRaw"/1048576" | bc -l)
sizeNumberDisplay=$(echo "scale=1;("$sizeNumber"*10)/10" | bc -l)

if [ $sizeDecimalDisplay == 0 ]
then
if (($(echo $sizeNumberDisplay" == "$sizeNumber | bc -l)))
then
size=$sizeRaw" bytes ("$sizeInteger"MiB)"
else
size=$sizeRaw" bytes (≈ "$sizeInteger"MiB)"
fi
else
if (($(echo $sizeNumberDisplay" == "$sizeNumber | bc -l)))
then
size=$sizeRaw" bytes ("$sizeNumberDisplay"MiB)"
else
size=$sizeRaw" bytes (≈ "$sizeNumberOne"MiB)"
fi
fi
fi

clear

echo "Book cover specifications for printing :"

if ((${#lenghtTotalCoverDisplay} == 4))
then
echo "Total lenght (front + side + back) = 0"$lenghtTotalCoverDisplay"mm"
else
echo "Total lenght (front + side + back) = "$lenghtTotalCoverDisplay"mm"
fi

if ((${#widthFrontBackCoverDisplay} == 4))
then
echo "Front width = 0"$widthFrontBackCoverDisplay"mm"
else
echo "Front width = "$widthFrontBackCoverDisplay"mm"
fi

if ((${#heightFrontBackCoverDisplay} == 4))
then
echo "Front height = 0"$heightFrontBackCoverDisplay"mm"
else
echo "Front height = "$heightFrontBackCoverDisplay"mm"
fi

if ((${#widthSideCoverDisplay} == 4))
then
echo "Side width = 0"$widthSideCoverDisplay"mm"
else
echo "Side width = "$widthSideCoverDisplay"mm"
fi

if ((${#heightFrontBackCoverDisplay} == 4))
then
echo "Side height = 0"$heightFrontBackCoverDisplay"mm"
else
echo "Side height = "$heightFrontBackCoverDisplay"mm"
fi

if ((${#widthFrontBackCoverDisplay} == 4))
then
echo "Back width = 0"$widthFrontBackCoverDisplay"mm"
else
echo "Back width = "$widthFrontBackCoverDisplay"mm"
fi

if ((${#heightFrontBackCoverDisplay} == 4))
then
echo "Back height = 0"$heightFrontBackCoverDisplay"mm"
else
echo "Back height = "$heightFrontBackCoverDisplay"mm"
fi

echo -e "\nBook content specifications for printing :"
echo "Number of pages = "$countPageTotal

if [ $countTable == 1 ]
then
echo "Total file size = "$size
else
echo "Total files size = "$size
fi
fi

read

exit 0

La routine présentée ci-dessus utilise les programmes (ou paquets) inkscape, librsvg2-bin, pdftk, et exiftool afin d'effectuer tous les traitements nécessaires.

Il vous faut donc les installer à l'aide de la ligne de commande suivante (à écrire dans le terminal de Linux) :

sudo apt-get install inkscape librsvg2-bin pdftk exiftool -y
Une fois cette installation effectuée, lorsque vous exécutez la routine (.sh), se propose à vous dans l'ordre d'apparition les questions suivantes :

Citer
- Page width in mm ? : largeur des pages (en millimètres).
- Page height in mm ? : hauteur des pages (en millimètres).
- Page margin in mm ? : dimensions des marges générales (en millimètres).
- Gutter margin in mm ? : dimension de la marge de reliure qui servira à positionner le texte en retrait par rapport à la reliure du livre (en millimètres).
- Font size in mm ? : taille des caractères du texte qui sera imprimé (en millimètres).
- Font name ? : police de caractère utilisée (elle doit être à espacement unique, par exemple "ubuntu mono").
- Cutter margin in mm ? : dimensions du fond perdu (en millimètres).

Lorsque vous validez cette dernière question, se propose à vous le choix "Sort option ?". Choisissez "a" (pour "Alphanumeric sort" ou tri alphanumérique) puis validez pour trier automatiquement les fichiers dans l'ordre alphanumérique, ou choisissez "m" (pour "Manual sort" ou tri manuel) pour effectuer vous-même le tri.

Si vous avez choisi l'option de tri "m", le menu "Manual sort :" (tri manuel) s'affiche à l'écran suivi de quelques commandes (détaillées ci-dessous), ainsi que l'arborescence des fichiers qui vont être inclus dans le livre, avec successivement le numéro d'apparition des fichiers et le chemin d'accès, c'est à ce moment que vous pouvez modifier l'ordre du tri. Voici ci-dessous le détail des commandes possibles :

Détail des commandes du menu "Manual sort :" :

Citer
- e (pour "Exit" ou sortie) permet de sortir du menu et commencer la génération du livre.
- s (pour "Save" ou sauvegarde) permet de sauvegarder l'arborescence de fichiers dans un fichier nommé file.tree.
- l (pour "Load" ou chargement) permet de charger le fichier nommé file.tree contenant l'arborescence de fichiers.
- d (pour "Delete" ou suppression) permet de supprimer le fichier nommé file.tree contenant l'arborescence de fichiers.

Utilisez ces options pour sauvegarder l'arborescence avec la commande "s", la modifier en ouvrant manuellement le fichier file.tree avec un éditeur de texte (comme gedit par exemple). Puis rechargez cette arborescence modifiée avec la commande "l", vous verrez les modifications s'afficher dans le menu "File tree :".

Plus bas le menu "File tree :" est affiché, c'est l'arborescence de fichiers :

La flèche orientée vers la gauche en suffixe des chemins d'accès aux fichiers indique la position de la destination d'un autre fichier source que vous pouvez choisir de déplacer. Validez pour décaler ce curseur vers une autre destination (c'est-à-dire vers le bas), ou écrivez un nombre, puis validez afin de changer la position dans l'arborescence (l'ordre de tri) du fichier indiqué en source (soit le nombre indiqué) vers la destination (soit le curseur en forme de flèche).

Exemple :
- Le curseur est positionné sur le fichier numéro 3, c'est la destination.
- J'indique le numéro 10, c'est la source, puis je valide.
- Le fichier en position 10 (la source) prend la position 3 (la destination), et inversement, le 3 prend la position 10.

Lorsque l'ordre de tri des fichiers correspond à ce que vous souhaitez, indiquez la commande "e" puis validez pour sortir du menu et débuter la génération du livre.

La génération du livre commence alors. Elle prend logiquement un temps proportionnel à la complexité de l'arborescence de fichiers utilisée comme source, ainsi que le nombre de lignes et de caractères dans la programmation et l'encodage de chaque fichiers. Une fois la génération du livre terminée, un fichier PDF nommé book content.pdf est constitué, et les spécifications utiles pour l'impression du livre sont affichées :

Citer
- Book cover specifications for printing : caractéristiques de la couverture du livre pour l'impression.
- Total lenght (front + side + back) : longueur totale de la couverture (soit la somme des largeurs de la face avant, du dos, et de la face arrière).
- Front width : largeur de la face avant.
- Front height : hauteur de la face avant.
- Side width : largeur du dos.
- Side height : hauteur du dos.
- Back width : largeur de la face arrière.
- Back height : hauteur de la face arrière.

- Book content specifications for printing : caractéristiques du contenu du livre pour l'impression.
- Number of pages : nombre total de pages du contenu du livre.
- Total files size : taille totale des fichiers de votre arborescence faisant partie du contenu, ce qui correspond à la taille totale des fichiers inclus dans le livre, autrement dit, le contenu utile (cette taille exclue donc les titres et la numérotation des pages, de même que la table des fichiers à la toute fin du livre qui n'est là que pour faciliter la navigation dans l'ouvrage final imprimé).

Toutes ces caractéristiques vont vous permettre de créer la couverture du livre manuellement. Dans la continuité, la génération de la couverture aurait pu être également automatisée, mais je pense que c'est contre-artistique, ne laissant plus aucun libre cours à la création et l'imagination. C'est donc un choix mûrement réfléchit de ma part que de laisser la création de la couverture à la charge de l'auteur.

Après avoir créé la couverture de votre livre à votre guise, il suffit simplement d'envoyer cette dernière ainsi que le fichier book content.pdf à un imprimeur !

Libre à vous de faire une utilisation de ce petit programme de génération automatique de contenu de livre, lorsque vous aurez besoin de sauvegarder vos fichiers sur un autre support que ceux habituellement utilisés dans le monde du numérique.

7
Merci pour la réponse,

Oui c'est une bonne solution sans doute, mais mon idée actuellement est de dispatcher la dissipation thermique sur plusieurs transistors, et non un seul, de sorte que les transistors pourraient etre montés sans dissipateur thermique contre le PCB. Je ne sais pas encore si c'est possible mais je vais experimenter pour voir.

8
Oui mais c'est ce que je souhaite, aux courants faibles un dropout faible, et dès que je viens chercher les 1A voir plus le dropout augmente, mais ça c'est pas important pour mes montages.

Comme ça, les montages basse consommation bénéficient d'un faible dropout, c'est le but, et les montages plus gourmands c'est pour de toute façon des utilisations avec des grosses batteries ou on peut tirer des ampères, la plupart du temps sur des LIPO qui ne viendrons jamais proche du dropout min...

Ce que j'obtiens actuellement très bien avec le LM2940 + MJE15033 qui fait venir du courant quand des servos moteurs fonctionnent par exemple... ou qui me donne du 5V en sortie à 5.5V environ en entrée lorsque je ne tire que max 100mA, testé et validé.

Tout ça est prévu et fonctionne bien, je souhaite juste un peu la même chose mais avec un TL431... Mais je vais experimenter en amateur et j'y arriverais, je demendais juste quelques idées sur le forum au cas ou.

J'aime pas le sifflement genre acouphènes des alims à découpage :(

9
Yffig merci pour les explications :)

Par contre le dropout de 0.5V je ne l'obtiens pas avec le LM78xx, c'est avec le LM2940 comme indiqué dans mon texte !

Merci quand même, je connais le configurateur de Ti et souhaite juste experimenter des choses en amateur avec des régulations linéaires.

10
Bonjour papyblue,

Du coup c'est impossible ce que je demande ? On ne peut pas mettre plusieurs NPN sur le TL431 ??

Merci d'avance.

11
En gros avec ce que vous m'expliquez (comprendre l'impossibilité de ce que je souhaite finalement), je me demande si le mieux ne serais t'il pas ce schéma :


(désolé pour la qualité du schéma c'est vite fait)

Mais c'est un exemple, j'aimerais ne pas en arriver à devoir mettre plusieurs TL431 !

Merci d'avance pour vos idées.

12
Merci pour les explications :)

Ok, du coup dans un autre montage, celui-ci :



J'avais selectionné après lecture des datasheets et tests empiriques le transistor pnp MJE15033, et remplacé le LM78 par un LM2940, pour une sortie de 5V selon le courant consommé si il est faible, je peux approcher une tension d'entrée de 5.5V sans problème, ça sort toujours du 5V régulé.

Vous ne pensez pas que ce soit possible avec le TL431 et un seul (pour l'exemple) 2SC6017 ?

Merci d'avance.

13
Bonjour Yffig, merci pour les précisions et explications :)

Je souhaite tirer grand max 500mA par transistor, tension de 5V en sortie, je pense mettre 4 à 8 transistors 2SC6017 (datasheet : https://www.onsemi.com/pub/Collateral/EN8275-D.PDF), ceux-ci m'intéressent car ils ont des Collector-to-Emitter Saturation Voltage assez faibles.

Merci d'avance pour votre aide !

14
Bonjour à vous :)

Je reviens vers vous avec ce schéma :


En effet ma question est : quel serait pour vous la meilleure solution afin de multiplier le nombre de transistors de puissance (en parallèles) dans ce montage ? (dans le but de répartir la dissipation thermique)

J'ai quelques idées et schémas posés sur papier, mais j'aimerais l'avis de personnes plus douées que moi à ce sujet. Je souhaite mettre des résitances de 1W 0.05 ohm à l'émetteur des transistors pour équilibrer les courants (si j'ai bien compris). Par contre je ne sais pas trop si il est mieux de placer le pont diviseur avant ou après ces résistances ballasts.

Merci d'avance pour votre aide.

15
Bonjour à vous :)

Oui vous avez raison, en tout cas j'espère aussi que cette vieille norme RS232 restera encore un petit peu sur les machines modernes, car j'aime bien son fonctionnement :)

Citer
Ton gyroscope sur ton quadri-hélicoptère, si je me trompe pas c'est un MPU-6050

Oui tout à fait, cela m'arrive souvent dans un premier temps d'utiliser des cartes toutes faites comme ce PCB en lien pour pouvoir développer rapidement les classes C++ qui permettent de faire fonctionner le composant.

Actuellement je dessine ma propre carte avec MPU6050 intégré afin de la monter en lieu et place de mes différents montages, et pouvoir la proposer au gens.

Citer
Tu pilotes tes contrôleurs moteurs par l'intermédiaire de ton microcontrôleur, tu le fais par PWM

Oui c'est ça, via la classe PwmWrite de MODULE.

J'ai utilisé 4 contrôleurs BLDC du commerce pour piloter mes 4 moteurs, mais depuis quelques temps je suis en train de développer mon propre contrôleur, voir ici :



Le proto fonctionne, mais il reste encore beaucoup de choses à améliorer et surtout à miniaturiser. Pour ce PCB j'ai étalé largement mes composants et j'en ai rajouté plus qu'il n'en faut pour tester des trucs :)

Dès que ce contrôleur brushless fonctionne exactement comme je le souhaite, je proposerai un plan, un montage, un programme C++ qui l'asservi, mais pour l'instant j'en suis très loin de la version finale.

Bonne journée

Pages: [1] 2 3