dimanche 30 août 2015

Digistump de Digispark

Oups! j'en discute déjà sur enfantin...

Un petit bidule amusant : une petite carte Digistump avec juste un ATtiny85 qui communique en USB 1.1 (schéma). L'AVR fonctionne sur son oscillateur interne (pas de quartz) et gère l'USB par software (Littlewire). Un bootloader (micronucleus) permet de charger des applications (avec un utilitaire 'micronucleus'). On trouve des clones du bidule pour moins de deux euros sur eBay. Il faut noter que ce n'est pas tellement le prix qui est intéressant; on trouve des solutions USB 2.0 pour à peine plus cher. C'est l'idée... Digispark fournit un environnement 'Arduino' modifié (un 'blob' de 20 MB (?)) mais il y a moyen de s'en passer et d'utiliser les commandes de base. Ainsi, le Makefile :
blink.elf: blink.c
        avr-gcc  -std=c99 -Wall -Os -mmcu=attiny85 -o blink.elf blink.c

blink.hex: blink.elf
        avr-objcopy -j .text -j .data -O ihex blink.elf blink.hex

flash: blink.hex
        micronucleus --run blink.hex
permet de compiler et télécharger le programme suivant :
#include <avr/io.h>
#define F_CPU 16000000UL
#include <util/delay.h>

int main(void)
        {
        DDRB  |= _BV(PB1);

        for (;;)
                {
                _delay_ms(100);
                PORTB ^= _BV(PB1);
                }
        }
(à vérifier : que le CPU tourne bien à 16 MHz; voir ici pour l'idée de se passer de l'IDE Arduino)

Ce qui serait bien, c'est d'utiliser Little-Wire pour créer une application avec un 'moniteur' capable d'interpréter des commandes que l'on enverrait en utilisant minicom via /dev/ACM0 ... Ce n'est pas standard (USB/CDC n'est pas sensé fonctionner en USB 1.0) mais cela devrait fonctionner. Ce n'est pas trivial (Little-Wire est délicat à utiliser et la documentation USB/CDC-ACM n'est pas très lisible) mais cela devrait être possible. Les codes disponibles ne font que quelques centaines de lignes.

Ce qui serait bien aussi, ce serait d'explorer d'autres AVR implémentant la même solution... (en réduisant le nombre de composants au strict minimum (voir ici)

(à suivre...)

dimanche 16 août 2015

Le DDS AD9850 et le Bus Pirate

HC-SR08 connecté au 'Bus Pirate'. N'étant pas sûr que le Bus Pirate pouvait fournir assez de courant, le module est alimenté par un 'MB102 Breadboard Power Supply Module'.

On trouve sur eBay un breakout, le HC-SR08, avec un générateur de signal sinusoïdal DDS AD9850. La datasheet nous apprend que le composant est configurable en envoyant 40 bits en série : 32 bits pour la fréquence (f=(x * CLKIN)/2^32 avec CLKIN = 125 MHz) et 8 bits de configuration (5 bits de phase et 3 de contrôle). Pour mettre le composant en mode 'série', il faut mettre la pin D2 à la terre et D1 avec D0 sur VDD. Le chip peut être alimenté en 3.3 volts. Les bits sont pris un par un au flanc montant de W_CLK et le tout est pris en compte au flanc montant de FQ_UD. En fait, cela ressemble très fort à du SPI et cela devrait être facile à mettre en œuvre avec un Bus Pirate, espèce de couteau suisse de la communication série pour ce genre de bidule. En utilisant la sortie CS pour FQ_UD, cela devrait même être trivial...

Aussitôt dit, aussitôt fait.
Pirate bus
----------
PB.GND  -- GND
PB.MOSI -----> DDS.DATA    # SPI bus
PB.CS   -----> DDS.FU_UD
PB.CLK  -----> DDS.W_CLK

DDS
---
DDS.GND -- GND

DDS.D0 -- 3.3V   # config serie
DDS.D1 -- 3.3V
DDS.D2 -- GND

DDS.VCC -- 3.3V

DDS.ZOUT1 ----------------> Oscillo.CH1
GND ----------------------> Oscillo.GND
Vient ensuite l'interaction avec le Bus Pirate... Sur Ubuntu, le driver du FTDI (USB-RS232) est natif, il n'y a qu'à utiliser 'minicom(1)' à 115200 bauds sur /dev/USB0, par exemple. Mettre le bidule en mode SPI, configurer les options et envoyer la séquence de bits.
$ minicom -D /dev/ttyUSB0 -b115200
[...]
HiZ>m
1. HiZ
2. 1-WIRE
3. UART
4. I2C
5. SPI
6. 2WIRE
7. 3WIRE
8. LCD
x. exit(without change)

(1)>5
Set speed:
 1. 30KHz
 2. 125KHz
 3. 250KHz
 4. 1MHz

(1)>1
Clock polarity:
 1. Idle low *default
 2. Idle high

(1)>1
Output clock edge:
 1. Idle to active
 2. Active to idle *default

(2)>1
Input sample phase:
 1. Middle *default
 2. End

(1)>1
CS:
 1. CS
 2. /CS *default

(2)>2
Select output type:
 1. Open drain (H=Hi-Z, L=GND)
 2. Normal (H=3.3V, L=GND)

(1)>2
Ready
SPI>L
LSB set: LEAST sig bit first
SPI>[0 0 0x25 0 0]
/CS ENABLED
WRITE: 0x00
WRITE: 0x00
WRITE: 0x25
WRITE: 0x00
WRITE: 0x00
/CS DISABLED  # ---> 70.42 khz mesuré
SPI>[0 0 0x26 0 0]
/CS ENABLED
WRITE: 0x00
WRITE: 0x00
WRITE: 0x26
WRITE: 0x00
WRITE: 0x00
/CS DISABLED # ---> 72.46 kHz mesuré
SPI>
Théoriquement, [0 0 0x25 0 0] devrait donner une fréquence de (37*256^2/256^4)*125 MHz, c'est-à-dire 70.572 kHz et [0 0 0x26 0 0], une fréquence de (38*256^2/256^4)*125 MHz, c'est-à-dire 72.479 kHz. La mesure à l'oscillo est un peu différente mais pas beaucoup : 2/1000 dans le premier cas et beaucoup moins dans le second. Il est fort probable que l'erreur soit du côté de la mesure plus que du côté de la génération (?). Pour 'qualifier' la fréquence générée, il faudrait utiliser un diviseur de fréquence et intégrer sur une plus longue durée; utiliser un fréquence-mètre calibré.