Fabrication industrielle
Internet des objets industriel | Matériaux industriels | Entretien et réparation d'équipement | Programmation industrielle |
home  MfgRobots >> Fabrication industrielle >  >> Manufacturing Technology >> Processus de fabrication

programmeur informatique de planche à pain

Composants et fournitures

Arduino UNO
× 1

À propos de ce projet

Quel est ce projet ?

Il s'agit d'une extension du projet d'ordinateur de maquette 8 bits de Ben Eater. J'ai énormément aimé suivre les vidéos de Ben sur la façon de construire un ordinateur de maquette et de créer ma propre version de celui-ci. Si vous n'avez pas suivi Ben, je vous recommande fortement de regarder ses vidéos avant de lire - ce projet n'aura que très peu de sens sans le contexte.

Après avoir construit l'ordinateur, il est rapidement devenu évident que si je devais basculer manuellement dans un programme via des commutateurs DIP à chaque fois que je l'allumais, il ne serait pas très utile du tout. Même basculer en seulement 16 octets encore et encore vieillit très vite. De plus, je prévoyais d'étendre la mémoire à 256 octets et cela n'allait être utile que si les programmes pouvaient être chargés et enregistrés.

Que puis-je en faire ?

  • Enregistrer un programme à partir de la RAM de l'ordinateur de maquette
  • Charger un programme dans la RAM de l'ordinateur de la maquette
  • Exécuter automatiquement un programme enregistré au démarrage de l'ordinateur de la maquette
  • Inspecter et modifier le contenu de la mémoire via une connexion série
  • Programmer l'ordinateur de la maquette en langage assembleur
  • Désassembler le contenu de la mémoire
  • Instruction en une seule étape par instruction
  • Définir des points d'arrêt et courir jusqu'au point d'arrêt

Voici une vidéo démontrant ces fonctionnalités. Veuillez excuser la qualité de la vidéo - je ne suis en aucun cas un créateur de contenu vidéo professionnel :

Comment ça marche ?

J'avais quelques objectifs en tête en réalisant ce projet :

  • Le moins de matériel possible requis pour le construire
  • Le moins de modifications possible sur l'ordinateur de maquette lui-même

Au début, j'ai pensé à utiliser une EEPROM pour stocker des programmes, puis une sorte de logique pour transférer des programmes de l'EEPROM à la RAM de l'ordinateur de la maquette. Cependant, proposer la logique de transfert s'est avéré plus compliqué que ce que je pouvais gérer (je suis plus un gars du logiciel même si j'aime vraiment travailler près du matériel). Il se trouve que je suis un grand fan d'Arduino, alors à un moment donné, j'ai commencé à penser à remplacer la logique de transfert par un Arduino. Il m'a fallu du temps pour me convaincre qu'utiliser un Arduino n'était pas de la triche (après tout même l'Arduino UNO est bien plus puissant que l'ordinateur de maquette lui-même) mais je suis content du résultat donc j'ai fait ma paix.

Alors, de quoi l'Arduino doit-il être capable ? Eh bien, il doit être capable de lire les données de la mémoire et d'écrire des données dans la mémoire. Le moyen le plus simple et le moins intrusif (pour l'ordinateur de la maquette) de le faire est d'utiliser la même interface que le module de mémoire possède déjà :le bus et les signaux de contrôle. Les broches d'E/S numériques Arduino sont bidirectionnelles, donc en connecter 8 directement au bus permet à l'Arduino de lire et d'écrire sur le bus. Pour que le module RAM lise ou écrive sur le bus, il suffit de régler les signaux MI/RI/RO en conséquence. Maintenant, ces signaux sont généralement pilotés par les EEPROM de la logique de contrôle, donc le fait que l'Arduino les contrôle également entraînerait des conflits et des situations de court-circuit possibles. Cependant, les EEPROM AT28C16 utilisées par Ben ont une entrée Chip Enable (CE) qui met toutes les sorties de données dans un état z élevé - ce qui permet ensuite à l'Arduino de manipuler les signaux. Pour lire la RAM, l'Arduino doit procéder comme suit :

  • mettre le signal CE de l'EEPROM au niveau haut (c'est-à-dire désactiver la logique de contrôle)
  • sortir la première adresse à lire sur le bus
  • mettre le signal MI élevé et attendre une transition d'horloge bas-haut
  • définissez MI bas et RO haut et attendez une transition d'horloge bas-haut
  • lire l'octet de données du bus
  • répétez l'étape 2 pour les 16 adresses
  • mettre le signal CE de l'EEPROM à un niveau bas (c'est-à-dire réactiver la logique de contrôle)

Et c'est tout. L'écriture du contenu de la RAM est très similaire, l'Arduino a juste besoin d'écrire sur le bus et de définir RI haut au lieu de RO. Il y a bien sûr quelques problèmes techniques à résoudre mais le mécanisme de base ci-dessus est le cœur de ce projet.

Quelles modifications dois-je apporter à l'ordinateur de la maquette ?

Deux modifications doivent être apportées :

  • Mettre des résistances pull-down sur les sorties de données de la logique de contrôle EEPROM
  • Désactiver (ou réinitialiser continuellement) le compteur de sonneries pendant que l'EEPROM est désactivé

Résistances pull-down

Les résistances pull-down sont nécessaires car une fois l'EEPROM désactivée, les résistances pull-up des portes logiques auxquelles les signaux de commande (tels que AO/AI/EO...) sont connectés vont tirer ces signaux vers le haut. Cela signifierait que plusieurs registres écriraient sur le bus, provoquant des conflits.

Les résistances de rappel sur les entrées des portes 74LS sont d'environ 10k. Les résistances pull-down doivent donc être suffisamment petites pour que la tension descende en territoire bas. Pour la plupart des lignes de signal, j'ai utilisé des résistances de 3,3 kOhm. Cependant, il y a deux exceptions :d'abord, le signal "SU" est connecté à 8 portes OU exclusifs, ce qui signifie que la résistance de rappel efficace est de 10kOhm/8 =1,25kOhm. Une résistance pull-down devrait être nettement inférieure à 1k pour atteindre ce niveau bas. Heureusement, le signal SU (soustraction) ne contrôle aucune interaction avec le bus, nous pouvons donc simplement l'ignorer et ne pas avoir de résistance pull-down. Deuxièmement, le CE (activation du compteur) avait besoin d'une résistance pull-down de 1k - des valeurs plus élevées provoquaient un comportement aléatoire du compteur de programme dans certains cas.

J'ai trouvé plus simple d'ajouter les résistances pull-down sur la maquette qui contient toutes les LED bleues, c'est-à-dire entre les anodes LED (qui sont connectées aux sorties EEPROM) et GND.

[Je n'ai pas pu installer les résistances ici pour les signaux HLT/MI/RI, j'ai donc ajouté celles à d'autres emplacements sur la maquette]

Réinitialisation du compteur de sonneries

L'autre modification est la réinitialisation du compteur de sonneries. Techniquement, ce n'est pas vraiment nécessaire pour permettre la sauvegarde/le chargement des programmes, mais cela permet un transfert en douceur du contrôle de l'Arduino vers la logique de contrôle. Le but est de maintenir le compteur de sonnerie à 0 tant que CE est haut (c'est-à-dire que la logique de contrôle est désactivée). Lorsque l'Arduino repasse CE à l'état bas (activant la logique de contrôle), le compteur en anneau sera à zéro et l'ordinateur de la maquette commence à exécuter l'instruction suivante.

Pour ma construction, je n'ai rien eu à faire pour cela car j'utilise une sortie EEPROM pour réinitialiser le compteur de sonnerie. Cela améliore les performances en réinitialisant le compteur de sonneries dès qu'une instruction est terminée. Il me donne également automatiquement la réinitialisation du compteur de sonnerie lorsque la logique de contrôle EEPROM est désactivée :la résistance de rappel sur la sortie de l'EEPROM tirera le signal vers le bas, ce qui réinitialise le compteur de sonnerie.

Si vous utilisez l'implémentation de Ben d'un compteur de sonnerie fixe à 5 étapes, je pense que l'extension suivante de son circuit de réinitialisation devrait réinitialiser le compteur lorsque si CE est élevé (cliquez sur les flèches gauche/droite ci-dessous pour basculer entre le circuit d'origine de Ben et le version étendue) :

Comme vous pouvez le voir, cela nécessite 3 portes NAND supplémentaires, c'est-à-dire une puce 74LS00 supplémentaire. Notez que je n'ai pas testé cette approche mais qu'elle devrait fonctionner d'après ce que je peux voir.

Cette modification n'est pas absolument nécessaire - vous pouvez la laisser de côté au début. Le chargement et la sauvegarde ainsi que le moniteur/assembleur/désassembleur fonctionneront toujours très bien. Cependant, toute action nécessitant un transfert de contrôle de l'Arduino vers la logique de contrôle ne fonctionnera pas. Plus particulièrement, il s'agit de l'exécution automatique des programmes enregistrés au démarrage ainsi que de l'exécution pas à pas et de l'exécution dans le débogueur.

Comment configurer l'Arduino ?

Téléchargez le croquis de l'archive GIT sur l'Arduino et connectez l'Arduino à l'ordinateur de la maquette comme suit :

  • Broche Arduino 5V (pas Vin !) au rail 5 V sur la maquette
  • Broche Arduino GND à broche GND sur la maquette
  • Broches numériques Arduino 2-9 au bus 0-7
  • Broche numérique Arduino 10 pour contrôler la sortie logique EEPROM qui contrôle RO
  • Broche numérique Arduino 11 pour contrôler la sortie logique EEPROM qui contrôle RI
  • Broche numérique Arduino 12 pour contrôler la sortie logique EEPROM qui contrôle MI
  • Broche analogique Arduino 0 au signal HORLOGE
  • Broche analogique Arduino 3 à CE (broche 18) de tous logique de contrôle EEPROMs et via une résistance de 10k à +5v

En dehors de cela, vous devrez câbler les broches d'entrée analogique 1 et analogique 2 de l'Arduino aux commutateurs DIP et aux boutons-poussoirs, comme indiqué dans les schémas (pour plus de détails, consultez le fichier Fritzing ci-joint).

Pour une version absolument minimale (mais toujours fonctionnelle), vous pouvez procéder comme suit :

  • Ajoutez des résistances pull-down de 3,3 kOhm aux broches de sortie EEPROM qui contrôlent AO, CO, EO, IO, RO
  • Ignorez les instructions "Réinitialiser le compteur de sonneries" ci-dessus
  • Faites le câblage de l'Arduino à l'ordinateur de la maquette comme indiqué ci-dessus (vous pouvez laisser de côté la résistance de 10k à la dernière étape si vous le souhaitez)
  • Connectez à la fois la broche analogique 1 et la broche analogique 2 à GND

Pour utiliser les boutons de chargement/sauvegarde, il vous suffit de connecter les boutons, les commutateurs DIP et les résistances associées aux broches analogiques 1 et 2 selon les schémas.

Pour utiliser la fonction de démarrage automatique, l'Arduino doit maintenir le compteur de programme et le compteur de sonnerie à 0 pendant la réinitialisation et pendant le transfert du programme. La résistance de rappel entre les broches analogiques 3 et +5V maintient la logique de contrôle désactivée (et donc le compteur de programme à 0) pendant que l'Arduino se réinitialise. Pour le compteur de sonneries, suivez les instructions "Réinitialisation du compteur de sonneries" ci-dessus.

Comment charger et enregistrer des programmes ?

La configuration minimale ci-dessus vous permettra de contrôler l'Arduino via l'interface série. Pour communiquer avec l'Arduino, vous aurez besoin d'un programme de terminal tel que Putty ou TeraTerm. Le moniteur série du logiciel Arduino fonctionnera également, mais la séparation entre les zones d'entrée et de sortie dans le moniteur série le rend un peu maladroit dans ce scénario.

  • Allumez l'ordinateur de la maquette
  • Connectez un PC à l'Arduino via le câble USB
  • Démarrez le programme du terminal et configurez à 9600 bauds, 8 bits, pas de parité, 1 bit d'arrêt
  • Appuyez sur ÉCHAP dans la fenêtre du terminal pour accéder au mode Moniteur
  • Vous devriez voir un "." en tant qu'invite de commande
  • Tapez "h" et appuyez sur Entrée pour obtenir une liste des commandes prises en charge

Avec la configuration minimale, vous devriez pouvoir utiliser les commandes "m", "M", "C", "l" et "s". Ceux-ci vous permettent de voir le contenu de la mémoire, de modifier le contenu de la mémoire et de charger et enregistrer des programmes.

Pour sauvegarder ou charger un programme via le bouton :

  • Éteignez l'horloge de l'ordinateur de la maquette
  • Réglez les commutateurs DIP pour sélectionner le numéro de fichier sous lequel les données doivent être enregistrées.
  • Appuyez sur le bouton "enregistrer" ou "charger". La LED connectée à CE s'allumera, indiquant que l'Arduino a pris le contrôle
  • Allumez l'horloge de l'ordinateur de la maquette. Vous devriez voir l'Arduino parcourir les adresses (regardez les LED du registre d'adresses mémoire)
  • Attendez que les LED du bus arrêtent de clignoter et que les LED du registre d'adresse mémoire affichent 1111
  • Éteignez l'horloge de l'ordinateur de la maquette. La LED connectée à CE s'éteindra, indiquant que le contrôle est revenu à la logique de contrôle

Pour exécuter automatiquement un programme au démarrage (assurez-vous que tous les circuits nécessaires sont en place), réglez simplement les commutateurs DIP sur le numéro de fichier sous lequel le programme est enregistré et allumez l'ordinateur de la maquette (ou appuyez sur le bouton de réinitialisation). Il existe deux cas particuliers :Si tous les commutateurs DIP sont éteints alors l'ordinateur démarre régulièrement, sans démarrage automatique. Si tous les commutateurs DIP sont activés, l'Arduino passe en mode moniteur directement au démarrage.

Comment utiliser l'assembleur et le désassembleur ?

Pour utiliser les fonctionnalités d'assembleur/désassembleur et de débogueur, vous devrez d'abord modifier le programme sur l'Arduino pour qu'il soit conforme à votre configuration spécifique. Recherchez la section dans le code source qui définit la structure opcodes_4bit :

struct opcodes_struct opcodes_4bit [] ={ {"NOP ", B00000000, 0, false}, {"LDA ", B00010000, 2, true}, ... {".OR ", B11111110, 0, true}, // définit l'adresse de début {".BY ", B11111111, 0, true}, // définit un octet de données {NULL, 0, 0, false} } ; 

Chaque ligne spécifie un opcode :

  • Le premier champ est le mnémonique ("LDA"). Pour un adressage immédiat, incluez un "#" dans le mnémonique. Donc ce que Ben appelle "LDI" s'appellerait "LDA #" ici. Pouvez-vous dire que j'ai grandi en programmant l'assembleur 6510 sur un C64 ?
  • Le deuxième champ est l'opcode lui-même. Les quatre bits inférieurs doivent toujours être à 0. (sauf pour les opcodes spéciaux .OR et .BY, voir ci-dessous)
  • Le troisième champ est le nombre de cycles nécessaires à l'exécution de l'opcode (en plus des cycles d'extraction). Par exemple, dans mon implémentation, LDA a l'opcode 0001 et prend un total de quatre cycles à exécuter, dont deux sont le cycle d'extraction. Si vous avez suivi les instructions de Ben (où tous les opcodes utilisent 5 cycles), cela devrait toujours être 3.
  • Le dernier champ spécifie si cet opcode requiert un argument. Par exemple, LDA requiert un argument mais pas OUT.

Vous devrez ajuster cette liste pour refléter les opcodes que vous avez implémentés pour votre ordinateur de maquette. Les deux dernières lignes sont des opcodes spéciaux utilisés par l'assembleur et doivent être laissés tels quels.

Après avoir entré tous vos opcodes, téléchargez le logiciel sur l'Arduino. Connectez votre terminal et passez en mode Monitor (soit en appuyant sur ESC dans la fenêtre du terminal, soit en activant tous les commutateurs DIP). Vous devriez maintenant pouvoir désassembler votre programme. Taper juste "d" dans le moniteur commencera le démontage à l'adresse 0.

L'assembleur est minimal mais fonctionne plutôt bien. Tapez "a" pour commencer l'assemblage à l'adresse 0. Les conventions sont :

  • Si une ligne ne commence pas par un espace, elle doit commencer par une définition d'étiquette. Les libellés doivent commencer par un caractère alphabétique suivi de caractères alphanumériques, peuvent comporter au maximum 3 caractères et sont sensibles à la casse.
  • Après le premier espace d'une ligne, l'assembleur attend un mnémonique (LDA, STA, OUT...).
  • Le mnémonique spécial ".BY" spécifie directement un octet de données à stocker à l'emplacement actuel.
  • Le mnémonique spécial ".OR" indique à l'assembleur de continuer l'assemblage à une nouvelle adresse.
  • Si un argument commence par un caractère alphabétique, il est supposé être une étiquette.
  • Tout argument numérique doit être un nombre décimal. Pour spécifier l'hexadécimal, faites précéder l'argument d'un "$". Par exemple, pour charger le nombre FF hexadécimal dans le registre A, utilisez "LDA #$FF".
  • Tout après un ";" est supposé être un commentaire et ignoré.

Par exemple, le code Fibonacci peut être saisi comme suit :

premier LDA #0; x =0 STA x LDA #1; y =1 STA y lp AJOUTER x; z =y + x STA z JC premier; redémarrer si débordement OUT; imprimer z LDA y; x =y STA x LDA z; y =z STA y JMP lp; boucle x .BY 0 y .BY 0 z .BY 0  

Quelles sont les limites ?

Pour économiser de l'espace RAM sur l'Arduino, l'assembleur fonctionne comme un assembleur à 1 passe (sinon l'Arduino devrait mettre en mémoire tampon tout le code source). L'assembleur écrit les opcodes dans la mémoire de l'ordinateur de la maquette au fur et à mesure qu'ils sont entrés. Cela signifie que l'assemblage est ralenti par la vitesse d'horloge de l'ordinateur de la maquette. Si vous copiez et collez du texte dans la fenêtre du terminal, cela peut entraîner la perte de caractères car l'Arduino ne peut pas suivre les caractères entrant à 9600 bauds (car il passe trop de temps à attendre l'horloge de l'ordinateur de la maquette). Pour contourner ce problème, réduisez le débit en bauds ou utilisez TeraTerm qui fournit un paramètre pour spécifier un délai entre les caractères envoyés. L'autre solution de contournement consiste à augmenter la vitesse d'horloge sur l'ordinateur de la maquette. Mon horloge monte à 160 kHz et à cette vitesse, je peux copier-coller du code à 9 600 bauds sans problème.

Dans sa configuration par défaut, l'esquisse Arduino peut gérer des fréquences d'horloge sur l'ordinateur de maquette allant jusqu'à environ 1-2 kHz (peut-être un peu plus). Notez que l'horloge de Ben dans sa configuration par défaut ne va pas plus vite que 500Hz. Si votre horloge est plus rapide, recherchez le #ifdef FAST_IO basculer dans le code. L'activation de FAST_IO devrait faire fonctionner l'Arduino avec des vitesses d'horloge allant jusqu'à 250 kHz. Je l'ai testé jusqu'à 160kHz. Il serait probablement possible de prendre en charge des vitesses plus élevées en implémentant les boucles à temps critique directement dans l'assembleur, mais honnêtement, une vitesse d'horloge de 160 kHz semble déjà trop rapide sur l'ordinateur de maquette avec ses capacités par ailleurs limitées. Assurez-vous de lire les commentaires correspondants dans le code avant d'activer FAST_IO.

L'Arduino a 1k d'EEPROM et peut donc contenir 1024/16 =64 programmes différents. En fait c'est 63 puisque 16 octets sont réservés pour sauvegarder les données de configuration. Ce n'est pas beaucoup mais probablement suffisant pour contenir tous les programmes que vous pouvez proposer. Seuls les programmes numéro 0-15 de ceux-ci peuvent être sélectionnés via les commutateurs DIP (1-14 pour le démarrage automatique) mais les commandes "s" et "l" fonctionneront avec toute la plage 0-62.

Ça a l'air un peu brouillon. Pouvez-vous le nettoyer?

Oui! Dans ma version finale ici, je viens d'utiliser la puce Atmega 328P nue (avec un cristal de 16 MHz et des condensateurs) au lieu d'un Arduino UNO. Le régulateur de tension sur l'UNO n'est pas nécessaire ici puisque l'Arduino utilise de toute façon directement le 5V de notre alimentation. La seule perte est que nous devons maintenant utiliser un convertisseur USB-série séparé (FTDI ou similaire) pour parler à l'Atmega. L'aspect général de celui-ci s'intègre bien mieux avec le reste de l'ordinateur de maquette :

Une autre optimisation consiste à supprimer le bootloader de l'Arduino/Atmega. Cela supprime le délai de 2 secondes pendant le démarrage du chargeur de démarrage Arduino. Je posterai des instructions sur la façon de le faire si les gens sont intéressés. Faites-le moi savoir dans les commentaires !

Code

Programmeur informatique de planche à pain
Le croquis Arduino pour le programmeur informatique Breadboardhttps://github.com/dhansel/programmer

Schémas

drive_pD8k28E85v.fzz

Processus de fabrication

  1. Souris d'ordinateur
  2. Contrôler un effet avec de vrais capteurs
  3. Arduino Spybot
  4. FlickMote
  5. Téléviseur maison B-Gone
  6. horloge maîtresse
  7. Trouvez-moi
  8. Puissance Arduino
  9. Tech-TicTacToe