Archive

Posts Tagged ‘Arduinos & Co’

Un scanner i2c autonome (suite)

27 février 2024 Laisser un commentaire

 » La suite, bientôt. », écrivais-je il y a peu…

Et bien, bientôt, c’est maintenant, toujours dans l’optique de « s’y remettre » (il n’y a pas que le sport dans la vie). Dans mon article précédent, j’ai réalisé un premier prototype de scanner i2c autonome.

Un premier prototype. En arrière plan à gauche, derrière la filasse, l’écran OLED de test. A droite l’afficheur à quatre chiffres. La carte Arduino est cachée par la plaquette d’essais.

L’Arduino est surdimensionné pour l’usage visé. On devrait pouvoir simplement utiliser un ATmega328 seul ou, mieux, un ATtiny85. Je n’ai pas de programmeur pour un ATMega. Je pourrais bricoler avec une carte Arduino ou une plaquette d’essais, mais ce sera pour plus tard. Je dispose en revanche d’un shield de programmation d’ATtiny85 🙂

Un clone de carte Arduino surmonté d’un shield de programmation pour ATtiny85.

Plutôt que de refaire un montage de A à Z, je préfère procéder par étapes, en deshabillant mon prototype pour monter le second.

Etape 1 : Deshabiller le premier prototype

L’afficheur TM1637 et le composant I2C à détecter sont déplacés vers une plaquette d’essais sans soudure. La carte Arduino peut maintenant être débarrassée sa plaquette d’essais. L’Arduino/son clone est toujours chef des opérations.

Au passage, je me suis rendu compte qu’il ne s’agit pas d’un Arduino Uno made by Arduino, mais d’un clone un amélioré.

A droite un clone de carte Arduino amélioré débarrassé de sa plaquette d’essai (à gauche). Ce clone possède 8 entrées analogiques contre 6 pour un Arduino Uno, et chacune des I/O est dupliquées vers un trio de pins comportant masse, alimentation et l’I/O en question. Comme quoi, un clone n’est pas forcément une version « cheap » de l’original.

Après avoir vérifié que cela fonctionne toujours, on peut passer à l’…

Etape 2 : Remplacer l’Arduino par un ATtiny85

J’ai commencé par placer l’ATtiny directement sur la plaquette d’essais, mais il aurait fallu lui faire faire des aller-retours vers le programmateur. L’ATTiny est donc installé sur une carte support, elle-même branchée sur le shield de programmation installé à son tour sur un clone d’Arduino Uno.

La carte support est également connectée à la plaquette d’essais par des fils de type « Dupont » :

  • Pin 1 prévus pour un bouton reset, mais non utilisée pour le moment
  • Pin 2 vers la pin CLK de l’afficheur à TM 1637
  • Pin 3 vers la pin DIO de l’afficheur à TM 1637
  • Pin 4 vers le rail GND (masse) de la plaquette d’essais
  • Pin 5 vers la pin SDA du composant I2C à détecter
  • Pin 6 inutilisée pour le moment
  • Pin 7 vers la pin SCL du composant I2C à détecter
  • Pin 8 vers le rail VCC de la plaquette d’essais.

Les rails GND et VCC de la carte support sont alors connectés, toujours par fils « Dupont » vers les pins GND et VCC de l’afficheur et du composant à détecter. Reste à relier les pins SDA et SCL vers le rail VCC via deux résistances à 4,7 KOhms. Ces dernières ne sont pas toujours nécessaires, car certains composants I2C en sont déjà équipés.

Ainsi installé, l’ATtiny85 est connecté à la fois au shield de programmation et à la plaquette d’essais. Lors de la programmation, la plaquette d’essais est simplement ignorée, et une fois la programmation terminée, le shield alimente l’ATTiny et le laisse prendre le contrôle de la plaquette d’essais via les fils Dupont.

« Reste » à passer à l’étape suivante, à savoir…

Etape 3 : Développer un peu de code et programmer de l’ATTiny85

J’ai adapté le code du premier prototype :

  • Remplacer la librairie Wire par TinyWireM
  • Modifier la valeur des « constantes » CLK et DIO
  • Enlever les affichages sur le port série

J’ai également dû modifier les délais d’affichage à 250 milli-secondes, car l’ATtiny semble tourner à un méga-Hertz au lieu des huit attendus.

Après quelques essais et erreurs (interversion des pins SCL et SDA, mauvaises valeurs pour CLK et DIO dans le code, le second prototype est fonctionnel.

Le code

// SPDX-FileCopyrightText: 2023 Carter Nelson for Adafruit Industries
//
// SPDX-License-Identifier: MIT
// --------------------------------------
// i2c_scanner
//
// Modified from https://playground.arduino.cc/Main/I2cScanner/
// Also modified by buje@free.fr : TM1637 4 x 7 segment display
// (code from https://lastminuteengineers.com/tm1637-arduino-tutorial/)
// --------------------------------------

#include <TinyWireM.h> // I2C Master lib for ATTinys which uses USI
#include <TM1637Display.h>

// Define the connections pins for TM1637

#define CLK 4
#define DIO 3

// Create a display object of type TM1637Display
TM1637Display display = TM1637Display(CLK, DIO);

#define DISP_DELAY 125

// Create an array that turns all segments ON
const uint8_t disp_allON[] = {0xff, 0xff, 0xff, 0xff};

// Create an array that turns all segments OFF
const uint8_t disp_allOFF[] = {0x00, 0x00, 0x00, 0x00};

const uint8_t disp_i2c[] = {
0x00,
SEG_C,
SEG_A |SEG_B|SEG_G|SEG_E|SEG_D,
SEG_G|SEG_E|SEG_D
};
const uint8_t disp_scan[] = {
SEG_A|SEG_F|SEG_G|SEG_C|SEG_D,
SEG_D|SEG_E|SEG_G,
SEG_A|SEG_B|SEG_C|SEG_E|SEG_F|SEG_G,
SEG_C|SEG_E|SEG_G
};
const uint8_t disp_version[] = {
0x00,
SEG_B|SEG_C,
SEG_A|SEG_B|SEG_C|SEG_D|SEG_E|SEG_F,
SEG_A|SEG_B|SEG_C|SEG_D|SEG_E|SEG_F
};
const uint8_t disp_err[] = {
SEG_A|SEG_D|SEG_E|SEG_F|SEG_F,
SEG_D|SEG_E
};
const uint8_t disp_done[] = {
SEG_B | SEG_C | SEG_D | SEG_E | SEG_G,
SEG_C | SEG_D | SEG_E | SEG_G,
SEG_C | SEG_E | SEG_G,
SEG_A | SEG_D | SEG_E | SEG_F | SEG_G
};
const uint8_t disp_none[] = {
SEG_C | SEG_E | SEG_G,
SEG_C | SEG_D | SEG_E | SEG_G,
SEG_C | SEG_E | SEG_G,
SEG_A | SEG_D | SEG_E | SEG_F | SEG_G
};


// Set I2C bus to use: Wire, Wire1, etc.
#define WIRE TinyWireM

void setup() {
WIRE.begin(); // initialize I2C lib

// 7 Segment display init
display.setBrightness(5);

}


void loop() {
byte error, address, index;
int nDevices;

display.setSegments(disp_i2c);
delay(DISP_DELAY);
display.setSegments(disp_scan);
delay(DISP_DELAY);

nDevices = 0;
index = 0 ;
for(address = 1; address < 127; address++ )
{

WIRE.beginTransmission(address);
error = WIRE.endTransmission(address);

// The i2c_scanner uses the return value of
// the Write.endTransmisstion to see if
// a device did acknowledge to the address.
error = WIRE.endTransmission();

if (error == 0)
{
display.setSegments(disp_allOFF);
display.showNumberHexEx(address, 0, false, 2, 2);
delay(DISP_DELAY);
nDevices++;
}
else if (error==4)
{
display.setSegments(disp_allOFF);
display.setSegments(disp_err, 2,0);
display.showNumberHexEx(address, 0, false, 2, 2);
delay(DISP_DELAY);
}

}

// Before exiting loop display some status
if (nDevices == 0) {
display.setSegments(disp_none);
} else {
display.setSegments(disp_done);
}

delay(DISP_DELAY); // wait 5 seconds for next scan
}

Conclusion provisoire, le prochain prototype

Et oui, vingt quatre heures, sept jours, tout-ça…

Ce second prototype est encore moins utilisable que le premier, vu qu’il faut se coltiner la plaquette d’essais et l’Arduino/programmateur/alimentation, mais on s’approche de la cible, étape par étape. Je pourrais aussi installer la carte support de l’ATtiny sur la plaquette d’essai et l’alimenter à l’aide de piles.

En arrière plan : une carte arduino (ici un clone) surmontée de son shield de programmation. L’ATtini85 est installé sur une carte d’adaptation reliée en bas au shield de programmation, et par les fils à l’afficheur quatre digits à droite, à gauche un écran OLED servant de cobaye. Tout à gauche un ATtiny inutilisé ici.

Le prochain prototype figurera sur une seule carte (strip-board ou proto-board, suivant la disponibilité) et regroupera dans l’idéal,

  • L’ATtiny85,
  • Son alimentation,
  • Un bouton Reset, toujours pratique
  • L’afficheur TM-1637,
  • Un connecteur mâle ainsi qu’un autre femelle pour y connecter les composants dont on voudra connaître l’adresse I2C.

Reste à sortir le carnet à croquis pour organiser tout ça.

Catégories :Réalisations Étiquettes : , , , , ,

Un scanner i2c autonome.

13 février 2024 Laisser un commentaire

J’ai parlé du bus I2C lorsque j’ai réinstallé ma Pi-Hole. Pour rappel, i2c est un bus de données et de commande simple, généralement entre un microcontrôleur et des périphériques identifiés chacun par une adresse fixée d’avance. La connectique I2C est simple, avec uniquement quatre connecteurs : alimentation, masse, horloge et données.

Dans l’article en question, il s’agissait d’un Raspberry Pi 1B en lieu et place du microcontrôleur, sur lequel était connectée une horloge sauvegardée par pile.

$ sudo i2cdetect -y 1
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: 50 -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- 68 -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --
$

Une Raspberry Pi ou toute autre carte du même type, c’est bien utile, mais ça n’est pas très pratique pour uniquement récupérer une adresse I2C ou deux. Il faut attendre que le système démarre, s’y connecter pour enfin lancer la bonne commande. C’est toujours mieux que de rechercher une énième fois l’information sur les internets.

Pour la simplicité, on peut faire mieux, par exemple avec un Arduino. On branche le composant, on connecte la carte Arduino sur le PC, on lance un terminal sur le bon port, et voilà.

Mon prototype est un clone d’Arduino couplé à connecté à une plaquette d’essai sur laquelle je peux connecter un afficheur et le ou les composants I2C à tester.

Un exemple de code ici : https://learn.adafruit.com/scanning-i2c-addresses/arduino

La mise en œuvre est déjà plus rapide que celle d’une Raspberry Pi, mais nécessite toujours un terminal pour l’affichage. C’est bien le cas quand on programme une carte Arduino, mais j’aimerais proposer quelque-chose de plus autonome qui afficherait les informations voulues dès son démarrage, sans avoir à passer par mon PC.

La cible visée

  • un Arduino réduit au strict minimum, à savoir un simple atmega328, voire un attiny85
  • un affichage numérique à sept segments
  • quelques connecteurs à quatre contacts pour les composants I2C à tester.

Mon prototype utilisera un Arduino Uno standard, mais n’importe quel clone ferait l’affaire.

A gauche un premier prototype basé sur un Arduino couplé à une plaquette d’essais.
A droite une carte Menta de chez Adafruit, que j’ai envisagé d’utiliser.

Afficheur numérique à sept segments

Il en existe de nombreux modèles. On pourrait également utiliser un afficheur LCD, mais ce serait peut-être sur-dimensionné. J’ai sélectionné un modèle pouvant afficher quatre digits. Le « : » situé entre chaque paire pourrait inciter à l’utiliser pour un horloge ou un chronomètre.

L’afficheur que j’ai sélectionné pour ce projet. A priori de l’i2c, mais… suprise !

Quatre connecteurs : GND, VCC, DIO et CLK. Ca ressemble fort à de l’I2C, alors testons la version actuelle du programme de détection…

… qui ne détecte rien. Allons bon ! Fichtre diantre !

Mea culpa. My bad. L’examen de la puce au dos de l’afficheur indique ‘TM 1637 » qui n’a pas d’interface i2c. Comme quoi RTFM, ou ici RTFC, c’est loin d’être inutile !

Un petit exemple d’utilisation ici : https://arduino-france.site/display-tm1637/

Premier essai : Une carte Arduino standard (série et afficheur)

Toujours sur mon prototype,

  • A4 et A5 côté Arduino connectés sur SDA et SCL du composant à tester
  • IO2 et IO3 côté Arduino sur DIO et CLK de l’afficheur

Le code

// SPDX-FileCopyrightText: 2023 Carter Nelson for Adafruit Industries
//
// SPDX-License-Identifier: MIT
// --------------------------------------
// i2c_scanner
//
// Modified from https://playground.arduino.cc/Main/I2cScanner/
// Also modified by John Butcher : TM1637 based 4 x 7-digit display
// --------------------------------------

#include <Wire.h>
#include <TM1637Display.h>

// Define the connections pins
#define CLK 2
#define DIO 3

// Create a display object of type TM1637Display
TM1637Display display = TM1637Display(CLK, DIO);

// Create an array that turns all segments ON
const uint8_t allON[] = {0xff, 0xff, 0xff, 0xff};

// Create an array that turns all segments OFF
const uint8_t allOFF[] = {0x00, 0x00, 0x00, 0x00};

const uint8_t disp_i2c[] = {
0x00,
SEG_C,
SEG_A |SEG_B|SEG_G|SEG_E|SEG_D,
SEG_G|SEG_E|SEG_D
};
const uint8_t disp_scan[] = {
SEG_A|SEG_F|SEG_G|SEG_C|SEG_D,
SEG_D|SEG_E|SEG_G,
SEG_A|SEG_B|SEG_C|SEG_E|SEG_F|SEG_G,
SEG_C|SEG_E|SEG_G
};
const uint8_t disp_version[] = {
0x00,
SEG_B|SEG_C,
SEG_A|SEG_B|SEG_C|SEG_D|SEG_E|SEG_F,
SEG_A|SEG_B|SEG_C|SEG_D|SEG_E|SEG_F
};
const uint8_t disp_err[] = {
SEG_A|SEG_D|SEG_E|SEG_F|SEG_F,
SEG_D|SEG_E
};
const uint8_t disp_done[] = {
SEG_B | SEG_C | SEG_D | SEG_E | SEG_G, // d
SEG_C | SEG_D | SEG_E | SEG_G,                 // o
SEG_C | SEG_E | SEG_G, // n
SEG_A | SEG_D | SEG_E | SEG_F | SEG_G // E
};
const uint8_t disp_none[] = {
SEG_C | SEG_E | SEG_G, // n
SEG_C | SEG_D | SEG_E | SEG_G,                 // o
SEG_C | SEG_E | SEG_G, // n
SEG_A | SEG_D | SEG_E | SEG_F | SEG_G // E
};



// Set I2C bus to use: Wire, Wire1, etc.
#define WIRE Wire

void setup() {
WIRE.begin();

Serial.begin(9600);
while (!Serial)
delay(10);
Serial.println("\nI2C Scanner");

// 7 Segment display init
display.setBrightness(5);

display.setSegments(disp_i2c);
delay(500);
}


void loop() {
byte error, address;
int nDevices;

Serial.println("Scanning...");

display.setSegments(disp_i2c);
delay(1000);
display.setSegments(disp_scan);
delay(1000);

nDevices = 0;
for(address = 1; address < 127; address++ )
{
// The i2c_scanner uses the return value of
// the Write.endTransmisstion to see if
// a device did acknowledge to the address.
WIRE.beginTransmission(address);
error = WIRE.endTransmission();

if (error == 0)
{
Serial.print("I2C device found at address 0x");
if (address<16)
Serial.print("0");
Serial.print(address,HEX);
Serial.println(" !");

display.showNumberHexEx(address, 0, false, 2, 2);
delay(2000);

nDevices++;
}
else if (error==4)
{
Serial.print("Unknown error at address 0x");
if (address<16)
Serial.print("0");
Serial.println(address,HEX);

display.setSegments(disp_err, 2,0);
display.showNumberHexEx(address, 0, false, 2, 2);
delay(2000);
}
}
if (nDevices == 0) {
Serial.println("No I2C devices found\n");
display.setSegments(disp_none);
} else {
Serial.println("done\n");
display.setSegments(disp_done);
  }
delay(5000); // wait 5 seconds for next scan
}

J’ai simplement modifié l’exemple de Carter Nelson de chez Adafruit. Du coup, ce sera licence MIT. LEs journées n’ayant que vingt-quatre heures, et les semaines que sept jours, j’ai manqué de temps, mais j’inclurai la licence MIT dans le dépôt chez Framasoft. Promis.

Une petite démo ?

La « victime » sélectionnée pour le test est un petit afficheur OLED. La carte Arduino est alimentée par une batterie portable Le diaporama ci-dessous est bidonné, suite à des photos un peu dégueu, mais la séquence d’affichage est respectée, et on y voit qu’avec un peu d’imagination, on peut afficher autre-chose que des chiffres de 0 à 9. Je corrigerai plus tard, si j’en trouve le temps.

Conclusion provisoire

J’ai atteint une partie de ma cible, à savoir un scanner i2c autonome à défaut d’être tout-à-fait pratique.

Mon prototype final. En haut à gauche un afficheur OLED de 0,9 pouce, victime du test, à droite l’afficheur à quatre chiffres. Le reste de l’espace est occupé par une belle filasse. Attention aux erreurs de connexion !

Suite à un manque de temps et d’énergie, j’en resterai là pour cet article, mais je travaille sur la prochaine étape, à savoir une carte réduite à sa plus simple expression, pour me passer de la carte Arduino, de la plaquette d’essais et de toute la filasse qui a transformé mon proto en nid à rat. La suite, bientôt.

Références

Catégories :Réalisations Étiquettes : , , ,

Contrôleur RGB, troisième version


La version 3 n’est qu’une mise au propre de la version 2 dont je n’ai d’ailleurs jamais parlé ici. Pour résumer, il ne s’agit ici que d’une réduction de format, et la partie logicielle ne change pas.

Contrôleur version 1

Le contrôleur, version 1

Cette première mouture pleinement fonctionnelle a été réalisée sur une plaquette de type stripboard, où il « suffit » de souder les composants, barrettes de connections, sockets, etc, de couper les pistes aux bons endroits, et d’ajouter les ponts nécessaires.

Le soucis est que l’ensemble prend beaucoup de place, et que trouver un boîtier à la bonne taille et à bon prix n’est pas très évident. J’aurais bien sûr pu en imprimer un à façon, je trouve qu’imprimer du « plat » – oui, un boîtier est un ensemble de plats – est un peu un gâchis de ressources. Avec une découpeuse – laser ou CNC – je veux bien, mais qu’une machine passe une heure ou deux à déposer du plastique pour faire une boîte…

Bref, le résultat prenait beaucoup trop de place à mon goût.

L’alimentation

Alimentation pour breadboard à gauche, sa remplaçante compact à droite

L’alimentation utilisée pour la version 1 est en réalité destinée à être utilisée sur une plaquette d’essais, ou breadboard. Elle permet d’alimenter deux rails en 5 ou 3.3 Volts, mais elle ne dispose pas de sortie en 12 Volts, et j’ai dû souder un fil supplémentaire directement sur le connecteur d’entrée. Fonctionnel, mais pas très propre.

Pour la version 2, j’utilise une alimentation plus compacte, permettant de se connecter en 3.3, 5 et 12 Volts. Cette nouvelle alimentation ne dispose malheureusement pas d’un des condensateurs visible près de la LED de sa grande sœur. A ce jour ça n’a jamais posé problème.

Contrôleur version 2

L’objectif principal, le gain de place est atteint en utilisant une plaquette pastillé de cinq par sept centimètres. Je n’aime pas trop les plaquettes pastillées, ou perfboards. Les pistes nécessaires sont remplacées par des fils soudés en place. Ça fait beaucoup de soudures, bien plus que nécessaire, mais je me suis plié à l’exercice.

Contrôleur version 2 non câblé.
Seuls les connecteurs et le réception infra-rouge sont en place

De gauche à droite et de haut en bas :

  • Connecteur d’alimentation 12 Volts
  • Connecteur d’alimentation 5 Volts
  • Connecteur Reset
  • Connecteur pour le clone d’Arduino (je n’ai pas de socket aux bonnes dimensions)
  • Le récepteur Infra-Rouge
  • Le socket pour l’UNL, contitué d’un socket 2×8 broches et d’un 2×4
  • Deux connecteurs pour bandes de leds RGB
Contrôleur V2 complet.

J’ai soudé les fils côté composants. C’est brouillon, les fils se croisent un peu partout, bref, un travail de sagouin, même si tout fonctionne correctement.

Contrôleur version 3

J’ai câblé les fils de signaux côté composants, et les fils d’alimentation de l’autre côté. L’implantation des connecteurs est strictement identique à celle de la version 2.

Le résultat est plus propre, même si j’ai encore des progrès à faire.

En haut, la version 1 dépouillée de ses composants
En bas à gauche, la version 2, également dépouillée
En bas à droite, la version 3

Deux connecteurs pour bandes de leds sont connectés au circuit UNL, mais pour le moment, seul celui du haut est piloté par l’Arduino. Un cavalier permet pour chacun d’en déconnecter l’alimentation.

Un petit bilan ?

L’objectif de réduction de taille est atteint. Même en comptant l’alimentation, je suis parvenu à diviser l’encombrement par deux.

Je me suis également amélioré sur la soudure, en m’appliquant et en m’aidant d’un éclairage suffisant et d’une bonne loupe.

Enfin, je devrais utiliser du fil plus fin, forcément moins encombrant et plus facile à placer.

Je préfère toujours les stripboards aux perfboards. Les deux formats ont leurs qualités et leurs défauts, et en respectant quelques principes simples, je sais m’accommoder des seconds. Ça tombe bien, car j’en ai un petit stocks, alors qu’il ne me reste qu’une seule stripboard. Je referai le plein quand les conditions seront meilleures.

La prochaine étape

Loger le contrôleur dans un boîtier, évidemment, et enrichir la partie logicielle.

Catégories :Arduino & Co Étiquettes : ,

Pico-puter : Cheap 8 Mk II

12 novembre 2019 Laisser un commentaire

Cheap 8 ?

Pico-puter est un nom par défaut. Ce doit être un ordinateur simple, voire simpliste, facile à comprendre et peu cher. Le mot anglais/étasunien « Cheap » convient tout à fait. Allons-y donc pour Cheap.

Et le « 8 » ? Pour cela il faut en revenir à la genèse du Pico-puter « Mk I ». L’AT Tiny qui l’accueille ne comporte que 512 octets de mémoire vive. Après réflexion, j’ai décidé d’en utiliser la moitié comme la RAM du pico-puter, le reste servant à l’émulation du microprocesseur. Il suffit d’une adresse sur huit bits pour adresser deux cent cinquante six octets. Huit bits d’adresses, huit bits de données, allez, va pour Cheap 8.

Plateforme cible

L’AT Tiny 85 reste ma cible, pour résumer :

  • 8 ko de mémoire programme
  • 512 octets de mémoire RAM
  • 512 octets de mémoire EEPROM
  • 5 pins pour les entrées et sorties
  • Possibilité de lien série, USB, I2C, I2S, etc via son USART programmable.

Pour l’exercice, cela m’oblige à appliquer les mêmes principes de programmation que pour le Mk I :

  • éviter l’héritage
  • utiliser la composition et la délégation
  • limiter au strict nécessaire l’utilisation de variables de travail, tant globales qu’internes aux classes
  • limiter le nombre de paramètres passés aux fonctions/méthodes
  • limiter la profondeur d’appel des fonctions/méthodes
  • ordonner les valeurs testées dans les clauses « switch »
  • diminuer la complexité tant matérielle que logicielle – le fameux « KISS principle »

Avant d’en arriver là, je me contente d’une …

Plateforme de prototypage

Il s’agit d’un Arduino Uno associé à un clavier à seize touches et un affichage à huit chiffres de sept segments. Clavier et affichage sont pilotés par l’intermédiaire d’un contrôleur TM 1638 très bien documenté et plutôt simple d’utilisation une fois qu’on en a compris le fonctionnement.

L’Arduino Uno et son micro contrôleur ATmega 328 est bien mieux doté en espace de travail qu’un AT Tiny : 8 ko de mémoire vive, 2 ko de mémoire EEProm, et 32 ko de mémoire programme (Flash). L’avantage est de pouvoir tester mon code avant d’en optimiser l’utilisation mémoire.

Et Cheap 8, dans tout ça ?

Les Arduino et les microcontrôleur AT Mega et Tiny peuvent se programmer en C++. C’est assez loin d’être « Cheap », tout ça. Il faut un ordinateur, un compilateur, un éditeur de texte, non ?

Comme pour le Mk I, je me suis inspiré de CHIP-8, qui est un ordinateur virtuel tournant à l’origine sur un ordinateur à base de microprocesseur RCA 1802, mais ensuite porté sur un peu tout ce qui peut se programmer, entre autres les ordinateurs huit bits, les PC et compatibles, les systèmes Windows, Linux et autres *NIXes, et les calculatrices HP 48 et suivantes.

Chip-8 exécute des instructions codées sur deux octets dans un espace mémoire de quatre kilo octets. Cheap 8, lui, exécute des instructions codées sur un octet dans un espace mémoire de deux cent cinquante six octets. Exit donc les graphismes et, pour le moment du moins, le son et les timers.

Organisation mémoire

Seize registres V0 à VF sont mappés sur les seize premiers octets de mémoire. V0 est l’accumulateur, VF le registre de flags. Par la suite, le registre VE sera utilisable comme registre d’index pour adresser facilement la mémoire disponible. Ce sera pour l’itération suivante.

Les seize derniers octets de la mémoire (adresses F0 à FF en hexadécimal) contiennent des adresses sous programmes (CALL) ou saut (JUMP), au choix du programmeur.

Le reste de la mémoire est occupé par le programme. Plus tard, il pourra contenir également des variables, une fois le registre d’index implémenté.

Registres

Seize registres, donc, notés V0 à VF. Des instructions permettent de copier ou d’échanger les valeurs entre V0 et les autres registres. Le registre VF, ou FLAG, est modifié par les opérations arithmétiques ou logiques, et est utilisé par les instructions de saut conditionnel.

Opérations arithmétiques et logiques

Ces opérations utilisent une pile d’évaluation, à la manière des langages de type Forth et plus généralement de type RPN.

Cette pile se trouve en dehors de la mémoire de Cheap 8, et n’est pas directement accessible. Seul le haut de la pile (TOS) est directement accessible via le registre V0. Le reste est utilisable pas les instructions de calcul arithmétiques et logiques.

Pile d’évaluation et pile de retour

La pile de retour permet de « revenir » à un fil d’exécution à la fin d’un sous programme (CALL).

Pile d’évaluation et de retour partagent seize octets situés en dehors de la mémoire Cheap 8. La pile d’évaluation grandit vers le haut, celle de retour vers le bas. Que les deux se croisent, le Cheap 8 arrête l’exécution du programme et passe en mode panique.

Les entrées et sorties

Un CPU, fut-il virtuel comme Cheap 8 a besoin qu’on lui fournisse des informations, et qu’il puisse nous en retourner. C’est essentiel pour lire un clavier, une ligne série ou afficher une valeur, des pixels ou des caractères.

CHIP-8 est doté des deux instructions IN et OUT pour interagir avec les périphériques. Pour le moment, huit ports d’entrée et huit ports de sortie suffiront largement

Clavier et affichage

Je me suis, pour cette partie, inspiré du Digirule 2A. J’ai bien tenté d’en acheter un, mais c’est comme pour les billets pour la Hell Fest, il faut s’accrocher pour obtenir le Graal.

Le Digirule 2A comprend :

  • un affichage d’une adresse mémoire en binaire sur huit leds
  • un affichage de la donnée pointée par cette adresse en binaire via huit leds
  • huit boutons pour modifier la donnée affichée
  • une série de boutons pour naviguer, lire et écrire dans la mémoire,
  • un bouton pour lancer ou arrêter l’exécution du programme

Organisation du Digirule 2a

Le format de mon clavier et de mon afficheur est différent :

Arduino Uno et la carte clavier/affichage piloté par un TM 1638.
Exemple d’affichage d’une valeur en décimal.

Les huit boutons du haut du clavier figureront les « Data Buttons » du Digirule. Ceux du bas ont des fonctions analogues aux boutons « Run/Stop », « Goto », etc du Digirule.

L’affichage numérique sera détourné pour figurer des leds.

Le code de Cheap 8

Le code compile sans erreur ni warning, et comprend le fonctionnement en mode programmation et exécution. En mode programmation, l’équivalent des Data Buttons fonctionne correctement, ainsi que les boutons de navigation, de lecture et de modification de la mémoire Cheap 8.

Reste à tester l’exécution correcte des instructions Cheap 8. Un affichage vers le port « série » de l’Arduino permet de suivre l’évolution des registres, de la mémoire, des boutons, et de l’afficheur, mais un vrai moniteur serait préférable.

Une fois le code stabilisé, le tout sera disponible sur Framagit, ce qui m’amène à …

Mon utilisation de Git via Framagit

Git est, entre autres, un gestionnaire de version de code source. J’ai choisi d’utiliser Git en ligne de commande, mais également via Framagit, qui est une interface pour utiliser Git, hébergée par l’association Framasoft.

Pour ce premier cycle, le dépot reste en mode privé. Mon code n’est pas encore très propre. J’ouvrirai l’accès quand je serai satisfait de mon travail.

Mon utilisation de Git, et de FramaGit, n’est pas très orthodoxe, notamment en ce qui concerne la gestion des bugs, ou « issues » en étatsunien, que j’utilise pour le moment comme une todo list.

Pour conclure …

… temporairement, du moins.

Ce projet a repris un élan qui me plaît bien. J’ai peu de temps à y consacrer, et je n’ai pas pu terminer cette première itération avant le début du NaNoWriMo. Je reprendrai ce travail plus tard – cf. cet article – étape par étape, en faisant taire tant bien que mal cette petite voix et son sempiternel « Et si… »

Catégories :Arduino & Co Étiquettes : ,

Pico-puter : Etat des lieux

13 août 2019 Laisser un commentaire

Cheap 8 Mk I

Il y a pas mal de temps, j’ai commencé à développer une espèce de pico-ordinateur à base d’ATtiny 85, avec un clavier réduit, une horloge, une petite mémoire flash , et un écran oled, le tout connecté via un bus à huit lignes — les huit de l’ATtiny 85 – et supportant le protocole I2C.

En tout, la RAM de l’ATtiny 85 se monte à 512 octets, plus 8ko pour la mémoire programme, un peu d’eeprom. Même avec les 4 ko de flash à côté de l’horloge RTC, ça fait réellement très peu. Je me suis inspiré de Chip 8, que l’on peut considérer comme l’émulation d’un ordinateur simple programmable directement en code machine.

De Chip 8, j’ai retiré tout ce qui a trait au graphisme, au son, réduit la mémoire à 256 octets, contre 4ko pour mon modèle, et réduit la taille des instructions à un octet. C’est encore plus léger, on pourrait dire « cheap », d’où le nom de « Cheap 8 » que j’ai retenu pour cette… hum… architecture.

Keep It Simple, Stupid !

Par contre, je me suis un peu emballé et ai créé toute une cathédrale d’appels au « matériel » dont un système de stockage primitif mais consommateur en espace programme. S’en est suivi une phase de debug laborieuse, et l’impression la certitude d’avoir fait trop complexe. Autre écueil, je n’ai prévu aucun moyen d’entrer du code dans ce pico-puter, et il faut ajouter un programme ad-hoc inclus dans le code source de « Cheap 8 ».

Je n’ai finalement jamais utilisé le bidule, mais rien n’est perdu. Le code de « Cheap 8 Mk I » est stocké dans mon dépôt mercurial perso, et il va me servir de base pour son successeur « Cheap 8 Mk II », qui devrait être beaucoup plus fun.

Cheap 8 Mk II

Cheap 8 MK II reprendra la base de son prédécesseur : une ALU à pile, 256 octets de mémoire programme et données, et quelques entrées/sorties. Pour l’utilisabilité, je me suis inspiré un peu de l’Altair, et beaucoup plus du « Digirule 2 » : quelques switches, une poignée de LEDs, et quelques artifices permettent d’examiner la mémoire, et de saisir un programme et de l’exécuter. Avec un Attiny85, les LEDs seront figurées sur l’écran OLED connecté en I2C, histoire d’économiser quelques-unes des pins au nombre déjà plus que compté. Je pourrais utiliser des LEDs avec quelques composants de type 74*595, mais ça ajouterait un peu de complexité.

Je conserve l’ATtiny 85 comme cible, mais pour des raisons pratiques, le développement se fera sur un Arduino UNO en gardant en mémoire les limites de l’ATtiny. La base du code actuelle prévoit déjà une bonne modularité, avec des fonctionnalités activées par quelques directives lors de la compilation, et ce principe sera reconduit.

La prochaine étape

La conception est quasiment terminée, à quelques détails près. J’ai une petite liasse de feuillets au format A5 contenant l’essentiel du projet. La prochaine étape est l’assemblage des switches. Suivra la partie codage.

Dernier détail, le Digirule est en open hardware, alors pourquoi ne pas faire de même ?

Eclairage à Leds : le code

20 janvier 2019 1 commentaire

Lors des « épisodes » précédents , j’ai assemblé un prototype, puis réalisé sur stripboard un montage plus ou moins définitif.

Le code, écrit dans l’IDE Arduino, est fonctionnel. Plutôt que d’appliquer la dichotomie habituelle, en séparant le programme source entre fichiers d’entête (.h) et fichiers de code (.cpp), j’ai préféré coder chaque classe dans son propre fichier, un peu comme le langage Eiffel.

Découpage du programme

Le programme principal (rgb_strip_controler.ino) demande au récepteur infrarouge (IrKeyPad.h) quelle commande a été envoyée par la télécommande et la    fait appliquer au contrôleur (controler.h). Ce dernier règle alors les niveaux rouge, vert et bleu de la bande de leds (RgbLed.h).

J’ai créé une classe pour chaque partie du programme :

  • debug.h : affichage de messages d’information sur le moniteur série de l’Arduino
  • RgbLed.h : réglage de l’intensité des trois couleurs de base d’une bande de leds RGB
  • IrKeyPad.h :  traduction des codes envoyés par la télécommande infrarouge en commandes (On, Off, etc)
  • Controler.h : envoie une liste d’actions à effectuer à la classe RgbLed, en fonction de ce qui est fourni par la télécommande infrarouge
  • rgb_strip_controler.ino : initialise le bousin, lit les commandes reçues et les fait appliquer par le contrôleur.

Quelques avertissements

  • Le code n’est pas commenté ou pas assez commenté (honte à moi). C’est sur ma « to do list »
  • Une seule bande de leds pour le moment. J’en ajouterai une seconde une fois le code commenté
  • Le débug n’est pas désactivable. C’est également sur ma « to do list »
  • Le code n’est pas optimisé, mais il est relativement lisible, même si j’ai quelques moments « WTF! » en le relisant
  • Je n’ai pas respecté tous les canons de l’orientation objet

Pour conclure

Ce code est fonctionnel, même si il peut et doit être amélioré.

Les prochaines actions de ce côté :

  • Ajouter des commentaires
  • Gérer une seconde bande de leds
  • Gérer l’activation et la desactivation des messages de debug

En attendant, j’ai déposé le code sur Framagit

Catégories :Arduino & Co Étiquettes : ,

Éclairage à leds : Réalisation

6 novembre 2018 4 commentaires

Mon contrôleur de leds RGB en est resté à… l’état de prototype. Un prototype fonctionnel et presque autonome avec son alimentation euh… intégrée. Il fait appel à des composants pour ainsi dire standard :

  • Bloc d’alimentation secteur, 12V en sortie, et assez d’ampères.
  • Convertisseur 12 volts vers 5 et 3.3 volts
  • Un clône d’Arduino Mini (5V, 16 MHz)
  • Un circuit UNL pour contrôler de petits moteurs ou des leds en PWM

ctrl_rgb_led_prptotype.jpg

Le circuit final est réalisé sur une plaquette type stripboard, et comprend plusieurs parties.

De gauche à droite :

  • Connecteur pour le convertisseur 12V vers 5V (je n’utilise pas le 3.3V sur ce projet)
  • Connecteur pour l’Arduino Mini
  • Connecteur pour le circuit UNL
  • Trois connecteurs pour trois bandes de leds …

En haut, un « rail » d’alimentation en 12 volts pour les bandes de leds.

En bas, une ligne de masse (0V) et une ligne d’alimentation en 5V

Chaque zone est reliée soit par les bandes conductrices du stripboard, soit par des fils en point à point.

Les connecteurs

Il s’agit essentiellement de barettes HE10 femelles. Le circuit UNL a, lui, droit à un connecteur du commerce, et trois barettes HE10 mâle serviront à connecteur des bandes de LEDs RGB. L’interrupteur (en bleu) n’a finalement pas été soudé sur la plaquette.

ctrl_rgb_led_connecteurs.jpg

Les fils de jonction

La majeure partie des bandes conductrices du stripboard ont été « coupées » pour isoler les différentes zones, et surtout isoler pour l’Arduino et l’UNL les pins droites et gauches.

Par convenance, les alimentations – 12 et 5V – sont câblées en rouge, et les masses en noir. Les signaux entre l’arduino et l’UNL et entre l’Arduino et le récepteur infra-rouge utilisent d’autres couleurs.

Esthétiquement, j’ai déjà fait mieux, mais les connections sont correctes… à part un défaut que je ne verrai que plus tard.

ctrl_rgb_led_fils.jpg

Le résultat

Les différents circuits sont fixés sur leurs connecteurs :

  • L’alimentation à gauche. Son fil 12 volts, en rouge, est connecté sur le rail 12 volts en haut de la carte.
  • L’Arduino mini au centre à gauche.
  • L’UNL au centre à droite
  • Le récepteur infra-rouge sous l’UNL
  • La bande de leds sur le premier connecteur en haut à droite.

Un pont à peine visible entre les pins 2 et 15 de l’UNL m’a donné une suée. Même en forçant les niveaux à 0, le bleu des RGB restait allumé. Après avoir identifié le pont avec un testeur de continuité, j’ai dû utiliser une loupe pour l’avoir en visuel. Un coup de mèche plus tard, tout rentrait dans l’ordre

ctrl_rgb_led_résultat.jpg

Les prochaines étapes

Plusieurs choses sont à voir, ou à revoir sur ce circuit.

  • Esthétiquement, on peut faire mieux, mais cette carte doit prendre place dans un boîtier. On ne verra à terme que l’interrupteur et la LED de l’alimentation, celles de l’Arduino, le récepteur infra-rouge et les trois connecteurs pour les bandes de LEDs.
  • Une fois l’alimentation branchée, le rail 12 volts est alimenté. Apparemment, c’est sans conséquence, mais par acquis de conscience, je vais lui ajouter un interrupteur.
  • Sur le dernier connecteur, seules deux couleurs pourront être utilisées, car la pin 9 du circuit UNL sert pour l’anti-retour nécessaire si on contrôle des moteurs à courant continu. Plutôt que d’utiliser une bande RGB sur ce connecteur, je pourrais me contenter de deux bandes de leds blanches. A étudier…
  • La programmation actuelle ne prévoit que l’utilisation d’une seule bande RGB. L’évolution du code est prévue, mais reste à valider.
  • Le contrôleur à l’origine de ce projet était sensé produire des animations, comme des effets de « pulse », des flashes, etc. Les sous programmes correspondants sont en place, mais sont vides pour le moment et restent à coder.
  • En cas de panne de la télécommande – pile épuisée ou autre – le contrôleur devient inutilisable. Une interface physique (boutons, variateurs, etc) pourrait prendre le relai, mais cela fera l’objet d’un autre projet.

En attendant la suite…

Novembre, c’est Nanovembre, et le NaNoWriMo prend tout mon temps libre. Ca laisse un bon mois pour laisser percoler de nouvelles idées pour améliorer ce qui peut l’être.

Creative Commons License

Catégories :Arduino & Co Étiquettes : ,

Éclairage à leds : le prototype

19 juin 2018 3 commentaires

Une impression 3D ne se passe pas toujours bien. La buse peut se boucher, le filament casser avant d’entrer dans le tube d’alimentation, le spool peut jammer, et il arrive même que ça flambe.

Je n’ai jamais eu à affronter le troisième cas, mais si cela arrivait, je préférerais m’en rendre compte dès le début du problème. Il vaut mieux avoir à changer quelques pièces que toute l’imprimante, ou même de maison pour cause d’incendie. Du coup, je garde un oeil sur l’impression en cours. Les petites impressions prennent vingt ou trente minutes, mais se déplacer pour vérifier la progression et l’absence de problème toutes les quelques minutes devient vite gênant, pour ne pas dire plus, parfois au point de ne pas pouvoir rester concentré sur autre-chose.

L’ajout d’une webcam a été une première avancée, mais sa résolution ainsi que son débit sont tous deux limités, et elle ne dispose pas d’un éclairage intégré. Sans demander du 4K, je préférerais avoir de bonnes images et pour obtenir de bonnes images, il faut un bon éclairage. En attendant de récupérer une meilleure webcam, commençons par l’éclairage du plateau.

Fiat lux !

Un ruban de leds RGB acheté pour quelques pièces dans un marché aux puces fera l’affaire.

rgb_led_strip_640

Ce ne sont pas des NeoPixels pilotables individuellement, mais de « simples » leds RGB montées en parallèle, avec tout de même leurs résistances protection. Le boîtier de commande et sa télécommande infra-rouge, sans oublier le bloc d’alimentation 12V sont un bonus bienvenu. Pourtant…

Et lux non fit.

La connexion du ruban de LEDs au boîtier de commande se fait par un connecteur qui ne fonctionne pas, malgré une apparence plus que convenable. Le boîtier ouvert, un test de continuité montre que le fil d’alimentation est rompu. On coupe, on remplace, on strappe, on teste et… toujours rien.

Sans alimentation, pas de lumière. Il existe d’autres points d’alimentation utilisables sur la carte électronique du boîtier. Tant qu’à faire, j’ai décidé de remplacer le connecteur « fancy » du boîtier par un bornier à vis. Mon multimètre a rendu l’âme, et son remplaçant n’a pas encore été livré, mais j’ai tout de même pu vérifier que le courant passe en pointant directement depuis le bornier vers le ruban de leds.

L’intensité est malheureusement insuffisante, malgré les tests et réglages à l’aide de la télécommande. Au lieu d’avoir des couleurs éclatantes, je n’ai qu’une très légère activation des leds. Apparemment le boîtier de commande hors service. Heureusement que le reste fonctionne !

Une solution, vite ! Un petit projet, on a dit.

Je pourrais passer des heures à tenter de comprendre ce qui ne fonctionne pas, mais je réserve l’exercice pour plus tard. Je vais « simplement » remplacer le boîtier par un équivalent.

Le ruban de leds mesure plusieurs mètres, largement trop pour mon projet, qui devrait en consommer une soixantaine de centimètres au plus. Il en restera assez pour d’autres usages. La télécommande fonctionne, ainsi que le bloc d’alimentation.

Le cahier des charges

Le nouveau boîtier de commande doit :

  • être utilisable avec une bande de 10 cm à 1 m
  • réutiliser la télécommande infra-rouge et le bloc d’alimentation
  • être facilement clôné
  • être facilement connectable et dé-connectable d’une bande de leds

Je me suis inspiré de plusieurs projets présentés sur youtube, instructables, et d’autres blogs pour développer ma petite solution à base d’Arduino :

  • Arduino Uno pour le prototype, un clone pour la cible
  • Récepteur infra-rouge
  • Commande de la bande de leds RGB via une puce UNL2803 commandée en PWM ( pseudo analogique)
  • Alimentation unique pour l’Arduino et la bande de leds

Première étape : piloter la bande de leds

L’UNL2803 est un petit circuit intégré à 20 18 pins permettant de piloter aussi bien des leds que de petits moteurs électriques. Il suffit de lui connecter une masse, les signaux d’entrée et les moteurs ou leds en sortie. Dans le cas d’un moteur, une pin supplémentaire doit être utilisée, pour éviter les « retours » de courant lors d’un arrêt de moteur.

Les pins 0 à 8 reçoivent les signaux PWM en provenance de l’arduino, les pins 10 à 17, juste en face, sont reliés aux leds ou moteurs à contrôler. Le pin 8 doit être relié à la masse, et le 9 ne sera pas utilisé.

La vitesse des moteurs ou l’intensité des LEDS peuvent être commandées finement en PWM – Pulse Width Modulation ou Modulation de longueur d’impulsion – et non en tout-ou-rien.

Dans mon cas, les connections sont les suivantes :

  • pin 0, 1 et 2 de l’UNL sur les pins 9, 10 et 11 de l’arduino
  • pin 9 de l’UNL sur la masse de l’arduino
  • pins 16, 17 et 18 de l’UNL sur les lignes Bleu, Vert, et Rouge de la bande de leds
  • ligne 12V de la bande de leds sur le 12V de l’alimentation
  • Masse de l’Arduino sur la masse de l’alimentation

Un petit programme trouvé ici permet de vérifier que tout fonctionne correctement. Les différentes couleurs devraient s’éclairer suivant une animation simple.

Seconde étape : identifier le type de télécommande infra-rouge

Là aussi, je me suis inspiré d’un travail existant. J’ai flashé sur l’Arduino un programme permettant de décoder ce qu’envoie chaque touche de la télécommande infra-rouge.

La librairie InfraRed pour l’Arduino offre largement assez de possibilité, et de multiples exemples permettent de s’y retrouver. Malheureusement, elle n’est pas directement utilisable dans mon cas. La classe (le module) sensée gérer le codage « NEC1 » se contente d’afficher des valeurs sur le port série de l’Arduino. Je pourrais lui ajouter ce qui manque (une simple routine de lecture en lieu et place d’un affichage), mais j’ai suivi une autre piste, celle de la librairie IRLib2, que j’ai découverte via un tutorial chez Adafruit.

L’exemple « comboDump » affiche le détail du signal reçu par l’Arduino et identifie le codage utilisé :

Decoded NEC(1): Value:F7E817 Adrs:0 (32 bits)
Raw samples(68): Gap:9364
Head: m9300 s4400
[ . . . ]
Space min:550 max:1750

C’est peu lisible, et j’ai abrégé, mais l’essentiel se trouve sur la première ligne : ma télécommande générique utilise le codage NEC, un classique du genre.

Troisième étape : décoder les touches de la télécommande

J’ai modifié la fonction loop() de l’exemple comboDump fourni avec la librairie IRLib2 pour afficher les codes des touches de la télécommande.

Une fois le programme flashé sur l’Arduino, le moniteur série de l’IDE Arduino affiche effectivement les codes envoyés par la télécommande, qu’il « suffit » de noter pour les utiliser dans le programme final :

Code : F730CF
Code : FFFFFFFF
Code : F708F7
Code : FFFFFFFF
Code : F700FF
Code : FFFFFFFF
Code : FFFFFFFF
Code : FFFFFFFF

Le code FFFFFFFF est un code de répétition, lorsque l’on appuie longuement sur une touche sans la relâcher.

Quatrième étape : choisir et programmer le comportement des LEDS

La télécommande doit permettre de :

  • allumer et éteindre les leds
  • augmenter et diminuer l’intensité des leds
  • allumer toutes les leds en blanc
  • sélectionner l’intensité d’une des trois couleurs
  • si possible sélectionner une animation des couleurs (flash, fading, etc)

Rien n’empêche de l’utiliser autrement, mais je vais tenter de copier le comportement d’origine. Le but premier est de produire de la lumière, pas de créer de nouveaux effets façon boîte de nuit

Toutes les fonctions, à part les quatre animations, devraient être assez simples à développer, en jouant sur le niveau des signaux en entrée de l’ULN.

Les animations demandent de jouer avec des temporisations, mais rien de vraiment compliqué à la base. Pour limiter les manipulations sur la télécommande pendant les tests, on pourra éventuellement flasher l’Arduino pour démarrer directement sur l’animation testée.

Le programme

Le programme final n’est pas très compliqué. A chaque exécution, la fonction principale effectue les actions suivantes :

  1. Si un signal infra-rouge valide est détecté, agir en conséquence :
    • changement d’animation
    • ou changement d’intensité d’une couleur
    • ou passage en mode « blanc » continu
    • ou allumer ou éteindre toutes les leds
  2. Mettre à jour l’intensité des leds suivant l’animation en cours

Le code sera disponible librement.

Bilan d’étape

Le montage et le programme fonctionnent correctement. Il me reste encore à coder les animations (flash, etc), mais pour l’instant cela peut attendre. Il suffira de reflasher l’Arduino.

Pour le moment le montage consiste en :

  • une carte arduino uno
  • une petite alimentation 12, 5 et 3.3V. Seul le 12V est utilisé pour le moment car l’Arduino est alimenté par sa prise USB
  • un breadboard supportant l’unl2803 et le récepteur infra-rouge
  • une bande de douze leds RGB
  • de la filasse pour relier le tout.
  • le bloc d’alimentation 12V
  • un petit transformateur 12V vers 5 et 3.3 V, pour le moment utilisé en 12V uniquement

unl2803_640

breadboard_640

led_strip_controler_640

Le programme comprend quatre modules :

  • affichage de messages sur un terminal série (xterm, putty, etc), pour suivre la progression du programme
  • lecture des signaux infra-rouge et décodage/transformation en numéro de touches
  • gestion des leds RGB
  • programme principal

Quelques liens utilisés

Les prochaines étapes

Ce projet n’aurait dû durer qu’une petite semaine, si le boîtier de contrôle d’origine avait fonctionné. J’y ai gagné au change, en découvrant le décodage de commandes infra-rouge, ainsi que le composant unl2803, qui permettent de contrôler de petits moteurs ou des leds RGB .

Pour termine complètement ce projet, il me reste à :

  • Améliorer et documenter le code
  • Rendre les sorties terminal série désactivables
  • Remplacer l’Arduino Uno par un Arduino Mini ou une Menta
  • Réaliser un boîtier et le câble de connexion d’une bande de leds

Pour le remplacement de l’Arduino Uno, la première option est d’utiliser une carte Menta dont la partie prototypage recevrait les composants du montage. La seconde est d’utiliser un clone d’Arduino mini. Vu l’encombrement, celle-ci a ma préférence.

arduino_menta_640

L’Arduino mini est posée sur la zone de prototypage de la carte Menta.

Encore quelques petites heures de travail en vue. Je documenterai cette seconde partie dans un prochain article en incluant le programme de l’Arduino.

Creative Commons License

Catégories :Arduino & Co Étiquettes : ,

Cheap8, un système pour le pico puter


(Cet article était planifié en… mai 2018, mais n’a jamais été publié. Vieux motard Japonais. )

Pour résumer le projet « Pico-Puter », il s’agit de concevoir, assembler et programmer un pico-ordinateur basé sur un ATTny85. A terme, il comprendra :

  • 512 octets de mémoire vive
  • 512 octets de mémoire EEPROM
  • 8 k octets de mémoire programme
  • un clavier 4×4 touches
  • un écran, une horloge RTC, et une mémoire EEPROM de 4k octets , le tout connecté via un bus I2C

Etat des lieux

J’ai assemblé :

  • une carte supportant un ATtiny85
  • une alimentation double 5V et 3.3V sur USB ou pile 9V
  • un fond de panier supportant un bus passif
  • l’écran OLED, une tinyRTC et son EEPROM

Je n’ai toujours pas réalisé le clavier.

Le choix du système

Je m’étais laissé quelques semaines pour décider du système :

Quelques semaines…
… Presque six mois ont passé, mais j’ai fait mon choix.

Cheap8

Je sais, ce n’est pas un nom très original très original. J’ai donc choisi un système de type chip8.

Pour rappel, Chip8 est une machine virtuelle créée, de mémoire, au début des années 70, et tournant sur des machines à base de processeur RCA 1802, comme le Cosmac ELF.

L’espace mémoire était limité à 4 k octets, code et variables compris, le clavier comportait seize touches et l’affichage se faisait en mode graphique sur une simple télévision. Les instructions occupaient chacune deux octets, et l’affichage de sprites était géré « nativement ». Une vraie machine de jeux ! A tel point qu’une version est sortie sur calculatrice HP 48.

Mon Cheap8 sera plus simple :

  • 256 octets de mémoire
  • 16 registres 8 bits V0 à VF superposés à 8 registres de 16 bits W0 à WF occupant les 16 premiers octets de la mémoire
  • V0 et W0 sont l’accumulateur pour les calculs. VF et WF forment le registre d’état (flags). Enfin, VE est un pointeur en mémoire.
  • Pas d’instruction d’appel de procédure (CALL), mais une table de vecteurs située en fin de mémoire
  • Une petite double pile, façon Forth, pour les évaluations (partie basse) et les adresses de retour (partie haute), située hors mémoire principale
  • Les instructions de calcul utilisent la pile d’évaluation, le registreV0 étant le haut de la pile
  • Certaines instructions permettent de sauter l’instruction suivante si le flag vaut 0 (SKNZ – SKip if Not Zero). Par exemple DEC I DEC ; SKNZrémente le registre I, puis incrémente le pointeur d’instruction de 1 si I vaut 0, de 2 sinon)
  • L’instruction 00 (I/O) permet d’effectuer des entrées/sorties vers les périphériques (écran, RTC, EEPROM, etc)

Les prochaines étapes

Le développement de Cheap8 ne devrait pas prendre trop de temps. Non content d’être très limité, cheap8 n’est pas très orthodoxe, mais pour une première approche, je pense que c’est une bonne base. L’important est d’apprendre.
Les prochaines étapes seront :

  • Développer et tester cheap 8
  • Développer les I/O d’affichage
  • Réaliser le clavier et les I/O nécessaires

Entre ça et mes autres projets en cours, difficile de prévoir une échéance.

Les articles précédents de la série

Creative Commons License

Catégories :Arduino & Co Étiquettes : ,

Pico puter : de la théorie à la pratique

19 septembre 2017 Laisser un commentaire

Mon mini cluster est cassé. Nœud principal HS. Diagnostic à venir. Du coup, je n’ai toujours pas de « vrai » serveur Mercurial…

En attendant, j’ai relu et (re-)*dé-coquillé mon premier NaNoWriMo (merci encore Titi !) , et j’ai un peu avancé sur mon projet de « Pico ordinateur« .

Yeps ! Les premiers écueils apparaissent à l’horizon.

Pour rappel, un ATtiny85 vu du programmeur, c’est :

  • 8 kilo-octets de mémoire flash pour les programmes et données statiques
  • 512 octets de mémoire RAM

Côté pratique, l’électronique est à l’avenant :

  • une masse et une alimentation
  • 1 reset qui peut éventuellement être utilisé comme entrée/sortie
  • 5 entrées/sorties, dont deux que je réserve pour le « bus » I2C
  • 512 octets de mémoire de stockage de type EEprom.
  • un capteur de température (si-si)
  • des timers
  • des interruptions

Bref, de quoi s’amuser, surtout vu ce que je compte lui adjoindre :

  • un petit écran OLED
  • un clavier 4 x 4 touches
  • une horloge/calendrier, sa ram intégrée sauvegardée par pile, ainsi que la mémoire EEProm qui l’accompagne
  • une entrée et une sortie « analogiques » dont l’usage reste à déterminer
  • d’autres petites choses connectées en I2C.

Ça parait léger.

De la théorie …

En principe, tout ça devrait se programmer sans trop de problèmes. I2C ici, I2C là, un clavier « lu » comme une entrée analogique, etc.

Eh bien, non !

… à la pratique

L’I2C n’est pas implémenté en matériel sur l’ATTiny85, et j’utilise une librairie ad-hoc. Et hop, quelques centaines d’octets consommés dans la mémoire flash du contrôleur, plus une quarantaine en RAM.

L’écran OLED a son petit protocole bien à lui, et il faut lui fournir le bitmap (5 octets) de chaque caractère à afficher. Un écran LCD 4×20 aurait été plus simple à programmer mais, je l’ai déjà dit, moins fun. Ce sera une solution de repli au cas où…

L’horloge RTC stocke l’heure et la date au format BCD dans sa RAM « non volatile » – comprendre, « sauvegardée par pile ». Elle propose au total dans cette RAM 64 octets de RAM dont l’usage d’une bonne partie est, à priori, laissé libre pour le programmeur. Hop, on ajoute un mini-protocole supplémentaire, et deux routines de conversion BCD <-> binaire.

L’EEPROM de trente deux kilo-bits  – 4 kilo octets – qui squatte la carte de l’horloge a, devinez quoi, son petit dialecte propre, mais c’est peut-être le composant le plus simple à utiliser dans ce projet.

J’oubliais l’EEPROM de l’ATtiny, utilisable librement, lui aussi. Heureusement, la librairie standard de l’Arduino suffit. Ouf !

Un peu d’unification

L’EEPROM de l’Attiny – 512 octets – , celle de la carte horloge – 4 kilo octets – , la RAM de l’horloge – 64 octets – ont des besoins assez simples. On peut les considérer comme des périphériques de stockage, mais à la base il faudra y lire et y écrire des valeurs, généralement un octet à la fois. Lent mais simple, et inversement.

Vu la mémoire RAM totale de l’ATtiny85 – 512 octets – ne pourrai pas je n’aurai pas à y manipuler de grosses structures. Partant de là, stocker ou récupérer des informations pourra se faire par paquets de huit, seize, trente-deux octets ou plus à la fois. Je ne suis pas encore fixé là dessus, mais un stockage « de masse » – tout est relatif – par blocs de 32 octets devrait suffire.

On sort son cahier, ses stylos, on dessine l’organisation générale du bousin, les classes, leurs héritages, bref, on fait ses plans, et on se retrouve avec plusieurs « périphériques » de stockage présentant les mêmes routines d’accès. Merci la POO ! Classe de base : I2C, classe abstraite stockage, une classe par périphérique, une pour le clavier, une pour l’écran. Ça a … de la classe !

** /me court se planquer comme un bourrin des Flandres **

Mise en oeuvre

L’écriture du code se passe bien. On joue un peu avec le C++. Et oui, l’IDE Arduino, à la base, c’est du C++ !

Les tests se déroulent bien, l’écran affiche, l’horloge donne la date et l’heure, sa RAM est lue et écrite sans soucis, idem pour sa colocataire l’EEPROM I2C, et le clavier attend sagement qu’on passe à l’étape du fer à souder, même si son code est presque terminé.

Bilan d’étape

La compilation donne :

Le croquis utilise 6862 octets (83%) de l’espace de stockage de programmes. Le maximum est de 8192 octets.
Les variables globales utilisent 439 octets (85%) de mémoire dynamique, ce qui laisse 73 octets pour les variables locales. Le maximum est de 512 octets.

6862 octets de flash utilisée, avec uniquement quelques tests, sans aucun logiciel de mon système cible (qu’il reste d’ailleurs à définir). Je suis encore confiant là-dessus : les tests prennent de la place qui sera à terme libérée pour autre-chose.

Mais 73 octets de RAM disponible ! SOIXANTE TREIZE ! Même si j’ai réservé 256 octets de RAM pour le futur système, clairement, ça va coincer. Un stack overflow sur PC, ça éclabousse un peu, mais là, ça va frotter sévère !

J’ai choisi la bonne méthode…

… pour un Arduino Mega (256 ko de flash, 8 Ko de RAM) , ou un Arduino Due (512 ko de flash, 96 ko de RAM). Pour un micro contrôleur beaucoup plus petit comme l’ATTiny85, il faut revoir sa copie car la programmation objet, pour sexy élégante qu’elle soit, n’est pas vraiment indiquée vu le peu d’espace disponible.

  • L’héritage, et en particulier la surcharge de méthodes couplée au polymorphisme consomment énormément de RAM.
  • Il vaut mieux utiliser la composition et la délégation. Les classes de bases fournissent les fonctions simples et se fichent éperdument de ce qu’on en fera. La classe auparavant héritée devient une classe chargée de les coordonner et leur déléguer les fonctions de base. On utilise plus de mémoire programme en flash, mais beaucoup moins de RAM. Si j’étais « jusqu’au bout-iste », je n’utiliserais que des fonctions (au sens C), mais la programmation orientée objet en mode light a quelques petits avantages.
  • Les attributs (variables internes) des classes consomment de la RAM. Il faut donc en limiter le nombre et la taille.
  • Les paramètres passés aux méthodes (fonctions) consomment de la pile, donc de la RAM. Même punition.
  • Les appels de méthodes consomment également de la pile pour les variables locales, mais uniquement lors de l’exécution de la méthode. A la sortie, de la pile est libérée, mais les appels de méthodes en cascade (et encore plus la récursion) multiplient d’autant l’utilisation de la pile. Il faut donc limiter les profondeurs d’appels. Un maximum de trois ou quatre fonctions/méthodes en cascade est une bonne règle. Pour les fonctions très simples (une ligne ou deux), préférer utiliser des macros (#define)
  • Même si ça reste à confirmer, les « switch » occupent apparemment moins de mémoire programme si les valeurs recherchées dans les clauses « case » sont triés par ordre croissant.
  • Les variables, attributs, fonctions et méthodes inutilisés n’occupent pas de mémoire de programme, mais complexifient le projet. Il faut rester simple.

Résumé simple de ce qui précède :

  • éviter l’héritage
  • utiliser la composition et la délégation
  • limiter au strict nécessaire l’utilisation de variables globales et de variables internes aux classes
  • limiter le nombre de paramètres passés aux fonctions/méthodes
  • limiter la profondeur d’appel des fonctions/méthodes
  • ordonner les valeurs testées dans les clauses « switch »
  • diminuer la complexité tant matérielle que logicielle – le fameux « KISS principle »

Après mise en pratique, la compilation de mon programme enrichi d’une foultitude de tests donne :

Le croquis utilise 7434 octets (90%) de l’espace de stockage de programmes. Le maximum est de 8192 octets.
Les variables globales utilisent 383 octets (74%) de mémoire dynamique, ce qui laisse 129 octets pour les variables locales. Le maximum est de 512 octets.

La RAM disponible pour la pile est maintenant de 129 octets sur les 512 que contient l’ATTiny85, toujours en réservant un bloc de 256 octets. Cela devrait suffire, même s’il faudra veiller au grain…

Les prochaines étapes

  • Décider du système qui animera le bousin. J’hésite toujours entre un Forth et un Chip-8 fortement dégraissé. Si j’étais cintré du chapeau, BrainF*, pourrait coller. Le Forth a ma préférence, mais avec un clavier 4×4, ça risque de ne pas être pratique.
  • Assembler et tester le clavier 4×4
  • Donner une fonction aux deux entrées/sorties encore libres

Mais d’abord

Un grand merci à Alex Wulff dont la « Business Card/Game Console » m’a donné plusieurs pistes pour mon projet, notamment le code de gestion de l’I2C et de l’écran OLED.

Creative Commons License

Catégories :Arduino & Co Étiquettes : ,