Un programmatore USB open source per PIC, ATMEL AVR, memorie seriali I2C-SPI-MicroWire-OneWire-UNIO,
dispositivi I2C e SPI
In breve
- Completamente gratuito e Open Source (GPL2, anche il firmware)
- Programma PIC10-12-16-18-24, dsPIC30-33, ATMEL AVR (serial e HV serial programming),
memorie seriali tipo 24xxxx (I2C), 25xxx (SPI), 93xx6 (MicroWire), DS24xx (OneWire), 11xxx (UNIO);
comunica con dispositivi I2C e SPI (vedi dispositivi supportati)
- Può funzionare da debugger ICD per alcuni modelli di PIC16F
- Interfaccia USB 2.0 Full Speed, classe HID (come tastiere, mouse ecc.)
- Auto alimentato
- Non ha bisogno di driver
- Componenti di facile reperibilità (costo stimato ~5€)
- Temporizzazioni gestite in hardware quindi veloce e
affidabile (scrive un 18F2550 in 10s)
- Non occupa la CPU e non risente di altri programmi in
esecuzione
- Programmi di controllo open source per Linux e Windows
- Non è un clone PicKit
Un render della scheda montata:
Un altro programmatore?
In questi ultimi anni [...così era nel lontano 2007], con la sparizione delle comodissime
interfacce seriale e parallela, gli appassionati
di elettronica si trovano sempre più in difficoltà nel
programmare i microcontrollori; i classici programmatori non funzionano
più e di solito si ricorre a convertitori
USB-seriale (che però non si possono comandare direttamente ma
solo via API, quindi lentamente) o a integrati di interfaccia da
aggiungere al programmatore, tipo gli FTDIxxxx, che sostanzialmente
appaiono come periferiche seriali o richiedono driver ad hoc. Ma
perché non usare i PIC stessi, che hanno l'USB nativo?
Cercando in lungo e in largo non sono
riuscito a trovare un programmatore USB che fosse funzionale, gratuito,
open source, e così ho deciso di costruirmelo. La filosofia open
source consiste nel fornire tutti gli schemi, sorgenti, informazioni
utili a costruire e modificare questo programmatore.
Firmware USB e HID (v0.12.0)
Per usare l'interfaccia USB sui PIC
è necessario un firmware che implementi una delle classi
definite dal consorzio USB o una nuova; io ho scelto la classe HID
perché è supportata in modo nativo da tutti i sistemi
operativi e quindi non necessita di alcun driver. La velocità
è più che sufficiente: in teoria si raggiungerebbero i
64KB/s, ma io ho misurato qualcosa come 20-40 KB/s, comunque sicuramente
abbastanza per programmare dispositivi di 1-100KB di memoria.
Come ogni periferica USB anche questa ha un identificativo vid e pid,
che di solito si compra dal consorzio USB; io ho ottenuto una coppia gratis da
pid.codes: 0x1209&0x5432;
sono entrambi configurabili a piacere
(previa compilazione), quindi lascio all'utente la scelta.
Il programmatore appare al sistema
come una periferica HID che comunica tramite pacchetti di 64 byte
scambiati con cadenza di 1ms.
L'implementazione del firmware USB viene da un progetto open source poco noto,
scritto da Alexander Enzmann, che io ho modificato e adattato al compilatore C18.
Ho anche scritto una
breve guida su come usarlo; per quanto
ne so io questo è l'unico firmware open source con supporto HID.
Il programmatore in se è semplicemente un interprete di comandi
che pilota direttamente le uscite del micro seguendo un apposito insieme di istruzioni.
Il ciclo di controllo principale aspetta che venga ricevuto un
pacchetto via USB, poi comincia a eseguire i comandi specificati
occupandosi tra l'uno e l'altro della comunicazione col pc; allo stesso
tempo gira la funzione di controllo del regolatore di tensione DCDC,
chiamata a intervalli regolari tramite un timer (e un interrupt).
Compilare il tutto richiede solo strumenti gratuti: MPLABX e MCC18 versione
studenti, disponibili sfortunatamente solo per il sistema (in)operativo a finestre.
Compilare con SDCC è sicuramente possibile ma richiede qualche modifica al sorgente.
Rilascio il tutto con licenza GPL2.
Qui
si trova il progetto MPLABX completo in formato compresso;
qui
il firmware compilato in formato hex per 18F2550;
qui
compilato per 18F25K50.
Programmi di controllo
La mia idea iniziale era di modificare un software già esistente, ad esempio winpic o picprog, ma
mi sono accorto che visto il tipo di comunicazione necessario, basato su pacchetti anziché
seriale, non avrei potuto adattarli facilmente, quindi ho dovuto scriverne uno (due) da zero.
Purtroppo, o per fortuna, non essendo un informatico professionista ho tagliato quasi tutto il superfluo:
l'interfaccia utente è davvero minima, ci sono sicuramente dei bachi che
mi impegno a eliminare, e mancano delle funzionalità come la modifica del codice a posteriori.
Però sono programmi molto snelli, piuttosto veloci, e non occupano la CPU per niente.
Quando possibile la scrittura viene verificata durante la programmazione, altrimenti immediatamente dopo.
Idealmente la versione del programma e del firmware dovrebbe essere la stessa, a parte
l'ultimo numero che indica piccoli cambiamenti e correzioni; in generale però ho cercato di
non stravolgere il protocollo con le nuove versioni, per cui a parte le novità introdotte in ogni rilascio è quasi
sempre possibile usare un programma nuovo con un firmware vecchio e vice versa.
A quanti si chiedono come mai non sia possibile programmare direttamente da MPLAB rispondo che
non ci sono difficoltà tecniche, ma la Microchip non rilascia informazioni di pubblico dominio su
come farlo; per averle bisogna essere dei produttori commerciali e firmare un contratto di non
diffusione, cosa evidentemente impossibile per un progetto open source GPL2.
Vice versa l'integrazione con Piklab è possibile e spero si farà presto; attualmente l'interfaccia
per programmatori custom è carente di alcuni parametri indispensabili, ma chi avesse tempo e voglia
può certamente modificare il codice e far funzionare il tutto.
Interfaccia grafica GTK, per Linux e Windows (v0.12.2)
OPGUI sfrutta le librerie GTK3, per cui su Windows è necessario installare anche il
Runtime Environment GTK3 (64 bit).
La schermata principale del programma:
In breve: i pulsanti sulla barra di comando permettono di leggere, scrivere, caricare e salvare file.
La scheda "Dati" presenta le informazioni su cosa fa il programmatore.
Sulla scheda "Dispositivo" si sceglie il dispositivo da scrivere o leggere e si possono modificare
alcune opzioni di programmazione, per esempio la scrittura delle locazioni ID, di calibrazione, l'uso della
eeprom ecc.; solo le impostazioni compatibili col dispositivo selezionato vengono prese in considerazione.
Tra le "Opzioni" ci sono: connessione col programmatore, errori ammessi in scrittura, salvataggio dei pacchetti
dati trasferiti, uso delle schede di espansione; con la funzione "Test Hardware" e un multimetro è possibile verificare
che il circuito stia effettivamente funzionando.
La scheda "I2C/SPI" permette di comunicare con dispositivi generici I2C e SPI;
se si utilizza il protocollo I2C bisogna sempre specificare il byte di controllo (e l'indirizzo se diverso da 0);
il bit RW viene gestito automaticamente.
Ad esempio per scrivere manualmente 3 byte su una 24xx16 all'indirizzo 64 si scrive: A0 40 1 2 3
Dalla versione 0.7.10 è incluso un debugger ICD per PIC16F, che funziona più o meno come
pdb, ma con supporto per file coff.
Su "I/O" si possono controllare manualmente le linee di I/O e le alimentazioni.
Con "Utility" si può convertire le singola linea di un file HEX in dati e vice-versa.
Non è previsto alcun programma di installazione; è sufficiente scaricare l'eseguibile e avviarlo.
Il programma scrive e legge file hex8 e hex32, e anche file binari per le memorie seriali.
Le lingue supportate sono Italiano e Inglese; per introdurre altre lingue bisogna generare il file languages.rc
(opzione -langfile) e modificarlo a piacimento; il codice della lingua è prima delle rispettive stringhe,
tra parentesi quadre [].
All'avvio il programma sceglie la lingua in base a quella del sistema operativo (si può anche forzare tramite l'opzione -lang).
Per abilitare l'accesso al programmatore su Linux vedi il capitolo
Accesso all'hardware sotto Linux.
Per maggiori informazioni scarica la
guida all'uso di OpenProg e Opgui o vedi la
guida al codice.
Compilazione (opzionale): bisogna avere installato le librerie GTK, GCC e i vari maketools
(MinGW/MSYS su Windows) e digitare:
> make
Successivamente per installare (su Linux, ma non è obbligatorio):
> make install
Scarica il programma ...
o i sorgenti
Interfaccia per linea di comando (Linux e Windows, v0.12.0)
OP è un eseguibile da linea di comando; la versione Windows non ha bisogno di installazione.
Si aspetta una periferica USB con vid&pid=0x1209:0x5432, se non specificato altrimenti.
Scrive e legge file hex8 e hex32 e anche binari per le memorie seriali.
Con l'opzione --HWtest e un multimetro è possibile verificare che il circuito stia effettivamente funzionando.
E' possibile comunicare via I2C e SPI con dispositivi generici diversi dalle memorie; nel caso I2C bisogna
specificare byte di controllo e indirizzo (o indirizzi) anche per una lettura;
il bit RW viene gestito automaticamente.
Nel caso di problemi o per pura curiosità si possono salvare tutti i dati scambiati col programmatore, tramite
l'opzione -l; per qualche strano motivo per specificarne il parametro opzionale bisogna usare
-l=<file> (chissà perché, sarà un baco della libreria getopt?)
Il supporto multilingue comprende Italiano e Inglese; si può ampliare generando e modificando il file languages.rc.
Opzioni:
-BKosccal carica BKosccal da file
-calib carica calibration da file
-command <messaggio> invia <messaggio> al programmatore ed esci
-cwX <cw> forza config word X
-d, device <disp.> dispositivo
-ee usa eeprom
-err <max> imposta massimo errori in scrittura
-fuse <val> scrive il byte fuse low (solo Atmel)
-fuseh <val> scrive il byte fuse high (solo Atmel)
-fusex <val> scrive il byte extended fuse (solo Atmel)
-h, help guida
-HWtest test hardware
-i, info informazioni programmatore
-i2c_r <N Ctr Ind> leggi N byte dal bus I2C
-i2c_r2 <N Ctr Ind(2)> leggi N byte dal bus I2C (indirizzi 16b)
-i2c_w <N Ctr Ind Dati> scrivi N byte sul bus I2C
-i2c_w2 <N Ctr Ind(2) Dati> scrivi N byte sul bus I2C (indirizzi 16b)
-i2cspeed <v> cambia velocità I2C: 0=100k, 1=200k, 2=400k, 3=800k
-icd <val> abilita ICD (goto indirizzo)
-id usa ID
-l, log [=file] salva registro
-lang <lingua> carica <lingua>
-langfile scrivi tutte le stringhe su file
-lock <val> scrive il byte lock (solo Atmel)
-mode <mode> SPI mode: 00,01,10,11
-osccal carica osccal da file invece che dal valore salvato prima della cancellazione
-p, path <percorso> percorso programmatore [/dev/usb/hidrawX]
-pid <pid> pid programmatore [0x5432]
-r, reserved leggi area riservata
-rep <n> dimensione report [64]
-s1, S1 programmazione multipla comandata da S1
-s, save <file> salva su file Ihex
-se, saveEE <file> salva EEPROM su file Ihex (solo ATxxxx)
-spi_r <N> leggi N byte dal bus SPI
-spi_w <N Dati> scrivi N byte sul bus SPI
-spispeed <v> cambia velocità SPI: 0=100k, 1=200k, 2=300k, 3=500k
-support dispositivi supportati
-use_BKosccal copia BKosccal su osccal
-v, version versione
-vid <vid> vid programmatore [0x1209]
-w, write <file> scrivi file Ihex
-we, writeEE <file> scrivi EEPROM file Ihex (solo ATxxxx)
Esempi:
> op -h #guida
> op -d 18F2550 -ee -s prova.hex #legge codice ed EEPROM e salva su file
> op -d 16F628 -ee -w prova.hex #scrive
> op -i2c_r 8 A0 0 #legge 8 byte dal bus I2C, byte di controllo A0, indirizzo 0
Un errore frequente è specificare il nome del dispositivo con lettere minuscole invece che maiuscole:
si scrive 16
F628, non 16
f628
Per abilitare l'accesso al programmatore su Linux vedi il capitolo
Accesso all'hardware sotto Linux.
Compilazione (opzionale): è presente un makefile, quindi per compilare bisogna avere installato GCC e i vari maketools
(MinGW/MSYS su Windows) e digitare:
> make
Successivamente per installare (su Linux, ma non è obbligatorio):
> make install
Per maggiori informazioni vedi la
guida al codice.
Ho incluso anche l'utility Hid_test, che spedisce e riceve un pacchetto (64 byte) alla volta; può
essere utile per fare qualche esperimento; in teoria ci si potrebbe addirittura scrivere uno script di programmazione.
Scarica i sorgenti
Accesso all'hardware sotto Linux
Su Linux i programmi si interfacciano col dispositivo /dev/hidrawX (/dev/usb/hiddevX prima della 0.11.2)
e hanno bisogno dei diritti di lettura/scrittura su quel dispositivo; è anche possibile specificarlo manualmente.
Ad esempio si può dare l'accesso a tutti con:
>sudo chmod a+rw /dev/hidraw1
Per evitare di doverlo fare ogni volta e abilitare permanentemente un utente alla lettura si può procedere come segue
(su Ubuntu e altre distribuzioni basate su Debian, verificare per le altre):
autenticarsi come root; creare un file /etc/udev/rules.d/10-openprogrammer.rules
nel caso si voglia abilitare un gruppo di utenti scrivervi:
KERNEL=="hidraw[0-9]", ATTRS{idProduct}=="5432", ATTRS{idVendor}=="1209", GROUP="<gruppo>", SYMLINK+="openprogrammer"
in cui <gruppo> è uno dei gruppi a cui appartiene l'utente (per un elenco digitare "groups", utilizzare un gruppo
adeguato e se necessario aggiungere l'utente al gruppo scelto ("addgroup <utente> <gruppo>").
oppure, nel caso si vogliano abilitare tutti gli utenti, cambiare solo i permessi di lettura:
KERNEL=="hidraw[0-9]", ATTRS{idProduct}=="5432", ATTRS{idVendor}=="1209", MODE="0664", SYMLINK+="openprogrammer"
riavviare udev per applicare le modifiche:
> udevadm control --reload-rules
> udevadm trigger
Ora, ogni volta che il sistema vede il programmatore, il corrispondente /dev/hidrawX avrà i permessi giusti e
verrà creato anche un link /dev/openprogrammer
Se collegando il programmatore non appare la periferica /dev/hidrawX (e il LED non
lampeggia a 1 Hz) è sufficiente eseguire alcune volte lsusb per forzare l'enumerazione da parte del sistema,
eventualmente staccando e riattaccando il cavo.
Interfaccia grafica MFC (non più aggiornata: v0.9.1)
OpenProg è scritto in VisualC++ 6.0 usando MFC.
Sono implementate solo le funzioni base di programmazione; è stata la prima interfaccia grafica del progetto,
ma ora lo sviluppo procede solo su OP/OPGUI.
Ha il solo vantaggio di funzionare senza alcuna libreria aggiuntiva.
Scarica il programma ...
o i sorgenti (progetto Visual Studio 6)
Come fare per ...
Cancellare un dispositivo: ogni dispositivo viene cancellato prima della programmazione; se comunque si volesse
cancellarlo basterebbe scrivere un file hex con dati validi (<0xFF) oltre lo spazio di memoria.
Per esempio, per i PIC12-16 il file sarebbe così:
:020000040000FA
:0144010000BA
:00000001FF
E per i PIC18:
:020000040002F8
:020000000000FE
:00000001FF
Altro metodo: OPGUI si avvia con i buffer di memoria pieni di 0xFF; basta quindi scrivere senza prima caricare alcun file.
Cambiare Configuration Word dei PIC:
Le Config Word sono di norma specificate nel file hex, ma si possono forzare per i PIC 10-12-16-18
tramite le opzioni del dispositivo (o da linea di comando).
In alternativa si può cambiare il sorgente e ricompilare; oppure bisogna modificare il file hex;
per i PIC16 i dati si trovano all'indirizzo 0x2007, che nel file corrisponde a 0x400E;
l'ultimo byte della riga in questione è il checksum, calcolato come complemento a 2 della somma dei byte della riga.
Per esempio:
:02400E00xxxxCC con xxxx nuovo valore e CC checksum
Cambiare la configurazione degli Atmel AVR: contrariamente ai PIC, che mappano la configurazione nella memoria
programma e quindi nel file hex, gli Atmel AVR devono essere configurati a mano, scrivendo il valore desiderato
dei byte di Fuse/Lock tra le opzioni del dispositivo; non è detto che sia necessario cambiare la configurazione
di fabbrica di tutti i byte, dipende dall'applicazione.
Risolvere l' "errore di sincronizzazione" con gli AVR:
Una possibile causa è la velocità troppo elevata della SPI in relazione a quella della CPU;
la frequenza interna deve infatti essere > 4 x frequenza SPI
Le innumerevoli impostazioni dei dispositivi potrebbero comportare che la CPU veda un clock anche molto basso;
il (nuovo) algoritmo di comunicazione varia automaticamente la velocità SPI in modo da entrare comunque in Program Mode.
Naturalmente più è bassa la velocità più si allungherà il tempo di lettura/scrittura; per velocizzare le operazioni
si potrebbe scrivere un file vuoto insieme con una configurazione ad alta velocità, e successivamente scrivere (velocemente)
il vero file con le impostazioni finali.
In alcuni dispositivi è possibile impostare frequenze estremamente basse (16 kHz), fuori dalla portata dell'algoritmo normale;
in questo caso l'opzione "scrivi Fuse Low @3 kHz" riesce a scrivere il byte Fuse Low; basta quindi specificare un valore che
riporti la frequenza a valori accettabili, e successivamente scrivere nel modo normale.
La seconda possibile causa è che la programmazione seriale è stata disabilitata: questo può essere fatto solo usando un programmatore parallelo,
e lo stesso è necessario per riabilitarla.
La terza causa è che in configurazione con risuonatore esterno il piedino X2 non è libero di muoversi; nel caso si usi l'espansione AVR
assicurarsi che X2 non sia a massa.
Verificare che un dispositivo sia vuoto: basta leggerlo ed esaminare i dati; vengono mostrate solo le righe con
dati <0xFF, quindi se non sono visualizzati dati il dispositivo è vuoto.
Verificare la corretta scrittura su un dispositivo: tutti gli algoritmi di scrittura eseguono una verifica dei dati,
alcuni durante la scrittura stessa, altri dopo; se il programma riporta 0 errori significa che effettivamente non ci
sono stati errori.
Se comunque si volesse fare una ulteriore verifica basterebbe rileggere dal dispositivo e confrontare i dati, tenendo
presente che non tutti i bit sono sempre implementati; per esempio i PIC16 vengono organizzati in word di
14 bit, quindi anche se nel sorgente viene indicato 0xFFFF questo viene scritto come 0x3FFF; inoltre le Config Word
hanno spesso dei bit fissi a 0 (che quindi non sono verificati).
Leggere l'area riservata: quasi tutti i PIC hanno un'area di memoria oltre le Config Word che è riservata per test
di produzione o calibrazione; per esaminarla basta abilitare la relativa opzione prima della lettura; nei PIC24-30-33
viene letta anche l'area di memoria executive.
Usare correttamente i valori di calibrazione e OscCal: in alcuni dispositivi (es. i 12F5xx) il valore di calibrazione
dell'oscillatore interno è scritto (in fabbrica) all'ultimo indirizzo della memoria programma e anche in una locazione
di riserva oltre l'area ID; dopo una cancellazione i programmi ripristinano il primo col valore
di riserva a meno che non venga specificato altrimenti; le altre opzioni sono: usare il valore salvato prima della
cancellazione (che di norma coincide con quello di riserva, a meno che uno dei due non sia stato cambiato prima),
usare il valore indicato nel file .hex.
E' inoltre possibile sovrascrivere il valore di riserva con quanto specificato nel file .hex, abilitando l'opzione
"programma ID e BKosccal"; in questo caso verranno scritte anche le locazioni ID, se specificate nel file.
Invece per sovrascrivere le locazioni di calibrazione bisogna usare l'opzione "programma Calib1 e 2"
Dispositivi supportati
Il programmatore è stato provato su un numero ristretto di dispositivi (quelli che posseggo e altri provati
da alcuni utenti) indicati in
neretto; gli altri sono supportati ma non collaudati; comunque, considerando che
per ogni famiglia di dispositivi almeno uno è stato verificato, dovrebbero funzionare tutti senza problemi.
Chi avesse la possibilità di verificarne la funzionalità è pregato di farmelo sapere.
Ugualmente chi avesse bisogno di ampliare il supporto o scrivesse altri algoritmi può contattarmi.
Nota bene:
I PIC serie LF sono usati come quelli F;
gli Atmel AVR con vari suffissi sono raggruppati se usano lo stesso algoritmo, es. ATmega8 e ATmega8A;
le memorie EEPROM comprendono tutte le versioni con VDDmax=5V, es. 242LC56, 24AA256, ecc.;
le EEPROM 93xx richiedono 2 algoritmi diversi, per la serie 93S e
per le altre, indicate come 93x (le 93xA hanno organizzazione a 8 bit);
le memorie SPI Flash richiedono un adattatore LV (vedi gli
schemi elettrici).
Supporto in lettura e scrittura:
10F200, 10F202, 10F204,
10F206, 10F220, 10F222,
10F320,
10F322,
12C508, 12C508A,12C509, 12C509A, 12F508, 12F509, 12F510, 12F519,
12F609, 12F615, 12F617, 12F629, 12F635, 12F675, 12F683,
12F752,
12F529T39, 12F529T48,
12F1501, 12F1571, 12F1572,
12F1612, 12F1822, 12F1840,
16F505, 16F506, 16F526, 16F527,
16F54, 16F57, 16F570, 16F59,
16F610, 16F616, 16F627, 16F627A,
16F628, 16F628A, 16F630,
16F631,
16F636, 16F639,
16F648A, 16F676, 16F677, 16F684, 16F685,
16F687,
16F688,
16F689, 16F690,
16F707,
16F716, 16F72, 16F720, 16F721,
16F722, 16F722A, 16F723, 16F723A,
16F724,
16F726, 16F727,
16F73, 16F737, 16F74,
16F747, 16F753,
16F76,
16F767,
16F77, 16F777,
16F785,
16F818, 16F819, 16C83, 16F83, 16F83A, 16C84,
16F84,
16F84A,
16F87, 16F870, 16F871, 16F872,
16F873, 16F873A, 16F874, 16F874A,
16F876, 16F876A, 16F877,
16F877A,
16F88, 16F882, 16F883, 16F884, 16F886,
16F887,
16F913, 16F914, 16F916, 16F917, 16F946,
16F1454,
16F1455, 16F1459,
16F1503,
16F1507, 16F1508, 16F1509, 16F1512, 16F1513, 16F1516, 16F1517, 16F1518, 16F1519,
16F1526, 16F1527, 16LF1554, 16LF1559, 16F1574, 16F1575, 16F1578, 16F1579,
16F1613, 16F1614, 16F1615, 16F1618, 16F1619,
16F1703, 16F1704, 16F1705, 16F1707, 16F1708, 16F1709, 16F1713, 16F1716, 16F1717,
16F1718, 16F1719,
16F1764, 16F1765, 16F1768, 16F1769, 16F1773, 16F1776, 16F1777, 16F1778, 16F1779,
16F1782, 16F1783, 16F1784, 16F1786, 16F1787, 16F1788, 16F1789,
16F1823, 16F1824, 16F1825,
16F1826, 16F1827, 16F1828, 16F1829, 16F1847,
16LF1902, 16LF1903, 16LF1904, 16LF1906, 16LF1907,
16F1933,
16F1934, 16F1936, 16F1937, 16F1938, 16F1939, 16F1946, 16F1947,
16F15213, 16F15214, 16F15223, 16F15224, 16F15225, 16F15243, 16F15244, 16F15245, 16F15254, 16F15255, 16F15256,
16F15274, 16F15275, 16F15276, 16F15313,
16F15323, 16F15324, 16F15325, 16F15344,
16F15345, 16F15354, 16F15355, 16F15356, 16F15375,
16F15376, 16F15385, 16F15386,
16F17114, 16F17115, 16F17124, 16F17125, 16F17126, 16F17144, 16F17145, 16F17146,
16F17154, 16F17155, 16F17156, 16F17174, 16F17175, 16F17176,
16F18013, 16F18014, 16F18015, 16F18023, 16F18024, 16F18025, 16F18026, 16F18044, 16F18045, 16F18046,
16F18054, 16F18055, 16F18056, 16F18074, 16F18075, 16F18076,
16F18114, 16F18115, 16F18124, 16F18125, 16F18126, 16F18144, 16F18145, 16F18146,
16F18154, 16F18155, 16F18156, 16F18174, 16F18175, 16F18176,
16F18313, 16F18323, 16F18324, 16F18325, 16F18326,
16F18344, 16F18345, 16F18346,
16F18424, 16F18425, 16F18426, 16F18444, 16F18445, 16F18446, 16F18455,
16F18456,
16F18854, 16F18855, 16F18856,
16F18857, 16F18875, 16F18876, 16F18877,
16F19155, 16F19156, 16F19175, 16F19176, 16F19185, 16F19186, 16F19195, 16F19196, 16F19197,
18F04Q40, 18F04Q41, 18F05Q40, 18F05Q41, 18F06Q40, 18F06Q41, 18F14Q40, 18F14Q41, 18F15Q40, 18F15Q41, 18F16Q40, 18F16Q41,
18F242, 18F248,
18F252, 18F258, 18F442, 18F448, 18F452,
18F458,
18F1220, 18F1230,
18F1320, 18F1330, 18F13K22,
18F13K50, 18F14K22,
18F14K50,
18F2220,
18F2221, 18F2320,
18F23K20, 18F23K22, 18F2321, 18F2331, 18F2410,
18F24J10, 18F24J11, 18F2420,
18F24K20, 18F24K22, 18F2423, 18F2431, 18F2439,
18F2450, 18F24J50, 18F24K50,
18F2455, 18F2458, 18F24Q71, 18F2480,
18F2510,
18F25J10, 18F25J11, 18F2515,
18F2520, 18F25K20, 18F25K22, 18F2523,
18F2525, 18F2539, 18F25K42, 18F25Q43,
18F2550, 18F25J50, 18F25K50, 18F2553, 18F25Q71, 18F2580, 18F25K80, 18F25K83, 18F2585,
18F2610,
18F26J11, 18F26J13, 18F2620, 18F26K20, 18F26K22, 18F26K42, 18F26Q43, 18F26J50, 18F26K50,
18F26J53, 18F26Q71,
18F2680, 18F26K80, 18F2682,
18F26K83, 18F26Q83, 18F26Q84,
18F2685,
18F27J13, 18F27K42,, 18F27Q43 18F27J53, 18F27Q83, 18F27Q84,
18F4220, 18F4221,
18F4320, 18F43K20, 18F43K22, 18F4321, 18F4331,
18F4410, 18F44J10, 18F44J11, 18F4420, 18F44K20, 18F44K22, 18F4423, 18F4431,
18F4439, 18F4450, 18F44J50, 18F4455, 18F4458, 18F44Q71, 18F4480,
18F4510, 18F45J10, 18F45J11, 18F4515,
18F4520, 18F45K20, 18F45K22, 18F4523,
18F4525, 18F4539, 18F45K42, 18F45Q43,
18F4550, 18F45J50, 18F45K50, 18F4553, 18F45Q71, 18F4580, 18F45K80,
18F4585,
18F4610, 18F46J11, 18F46J13, 18F4620,
18F46K20, 18F46K22, 18F46K42, 18F46Q43, 18F46J50, 18F46K50,
18F46J53, 18F46Q71,
18F4680, 18F46K80, 18F4682, 18F46Q83, 18F46Q84,
18F4685,
18F47J13, 18F47K42, 18F47Q43, 18F47J53, 18F47Q83, 18F47Q84,
18F54Q71, 18F55K42, 18F55Q43, 18F55Q71, 18F56K42, 18F56Q43, 18F56Q71, 18F56Q83, 18F56Q84, 18F57K42, 18F57Q43, 18F57Q83, 18F57Q84,
18F63J11, 18F63J90, 18F64J11, 18F64J90,
18F65J10, 18F65J11, 18F65J15, 18F65J50, 18F65J90, 18F65K80,
18F66J10, 18F66J11, 18F66J15, 18F66J16, 18F66J50, 18F66J55, 18F66J60, 18F66J65, 18F66J90, 18F66J93,
18F67J10, 18F67J11, 18F67J50, 18F67J60, 18F66K80, 18F67J90, 18F67J93,
18F83J11, 18F83J90, 18F84J11, 18F84J90, 18F85J10, 18F85J11, 18F85J15, 18F85J50, 18F85J90,
18F8520, 18F86J10, 18F86J11, 18F86J15, 18F86J16, 18F86J50, 18F86J55, 18F86J60, 18F86J65,
18F86J72, 18F86J90, 18F86J93,
18F8722, 18F87J10, 18F87J11, 18F87J50, 18F87J60, 18F87J72, 18F87J90, 18F87J93,
18F96J60, 18F96J65,
18F97J60,
24F04KA200, 24F04KA201,
24F08KA101, 24F08KA102,
24F16KA101, 24F16KA102,
24FJ16GA002, 24FJ16GA004,
24FJ32GA002, 24FJ32GA004, 24FJ32GA102, 24FJ32GA104,
24FJ32GB002, 24FJ32GB004,
24FJ48GA002, 24FJ48GA004,
24FJ64GA002, 24FJ64GA004, 24FJ64GA006, 24FJ64GA008, 24FJ64GA010,
24FJ64GA102, 24FJ64GA104, 24FJ64GA306, 24FJ64GA308, 24FJ64GA310,
24FJ64GB002, 24FJ64GB004, 24FJ64GB106, 24FJ64GB108, 24FJ64GB110,
24FJ64GC006, 24FJ64GC008, 24FJ64GC010,
24FJ96GA006, 24FJ96GA008, 24FJ96GA010,
24FJ128GA006, 24FJ128GA008, 24FJ128GA010, 24FJ128GA106, 24FJ128GA108, 24FJ128GA110,
24FJ128GA306, 24FJ128GA308, 24FJ128GA310,
24FJ128GB106, 24FJ128GB108, 24FJ128GB110, 24FJ128GB206, 24FJ128GB210,
24FJ128GC006, 24FJ128GC008, 24FJ128GC010,
24FJ128DA106, 24FJ128DA110, 24FJ128DA206, 24FJ128DA210,
24FJ192GA106, 24FJ192GA108, 24FJ192GA110,
24FJ192GB106, 24FJ192GB108, 24FJ192GB110,
24FJ256GA106, 24FJ256GA108, 24FJ256GA110,
24FJ256GB106, 24FJ256GB108, 24FJ256GB110,
24FJ256GB206, 24FJ256GB210,
24FJ256DA106, 24FJ256DA110, 24FJ256DA206, 24FJ256DA210,
24EP32GP202, 24EP32GP203, 24EP32GP204,
24EP32MC202, 24EP32MC203, 24EP32MC204,
24EP64GP202, 24EP64GP203, 24EP64GP204, 24EP64GP206,
24EP64MC202, 24EP64MC203, 24EP64MC204, 24EP64MC206,
24EP128GP202, 24EP128GP204, 24EP128GP206,
24EP128MC202, 24EP128MC204, 24EP128MC206,
24EP256GP202, 24EP256GP204, 24EP256GP206,
24EP256MC202, 24EP256MC204, 24EP256MC206,
24EP512GP202, 24EP512GP204, 24EP512GP206,
24EP512MC202, 24EP512MC204, 24EP512MC206,
24HJ12GP201,
24HJ12GP202,
24HJ16GP304,
24HJ32GP202, 24HJ32GP204, 24HJ32GP302, 24HJ32GP304,
24HJ64GP202, 24HJ64GP204, 24HJ64GP206, 24HJ64GP210, 24HJ64GP502,
24HJ64GP504, 24HJ64GP506, 24HJ64GP510,
24HJ128GP202, 24HJ128GP204, 24HJ128GP206, 24HJ128GP210,
24HJ128GP306, 24HJ128GP310, 24HJ128GP502, 24HJ128GP504, 24HJ128GP506, 24HJ128GP510,
24HJ256GP206, 24HJ256GP210, 24HJ256GP610,
30F1010, 30F2010,
30F2011, 30F2012,
30F2020, 30F2023,
30F3010, 30F3011, 30F3012, 30F3013, 30F3014,
30F4011,
30F4012, 30F4013,
30F5011, 30F5013, 30F5015, 30F5016,
30F6010, 30F6011, 30F6012, 30F6013, 30F6014, 30F6015,
33FJ06GS101, 33FJ06GS102, 33FJ06GS202,
33FJ12GP201,
33FJ12GP202, 33FJ12MC201, 33FJ12MC202,
33FJ16GP304, 33FJ16GS402, 33FJ16GS404, 33FJ16GS502, 33FJ16GS504, 33FJ16MC304,
33FJ32GP202, 33FJ32GP204, 33FJ32GP302, 33FJ32GP304,
33FJ32GS406, 33FJ32GS606, 33FJ32GS608, 33FJ32GS610,
33FJ32MC202, 33FJ32MC204, 33FJ32MC302, 33FJ32MC304,
33FJ64GP202, 33FJ64GP204, 33FJ64GP206, 33FJ64GP306, 33FJ64GP310,
33FJ64GP706, 33FJ64GP708, 33FJ64GP710, 33FJ64GP802, 33FJ64GP804,
33FJ64GS406, 33FJ64GS606, 33FJ64GS608, 33FJ64GS610,
33FJ64MC202, 33FJ64MC204, 33FJ64MC506, 33FJ64MC508, 33FJ64MC510,
33FJ64MC706, 33FJ64MC710, 33FJ64MC802, 33FJ64MC804,
33FJ128GP202, 33FJ128GP204, 33FJ128GP206, 33FJ128GP306, 33FJ128GP310, 33FJ128GP706,
33FJ128GP708, 33FJ128GP710,
33FJ128GP802, 33FJ128GP804,
33FJ128MC202, 33FJ128MC204, 33FJ128MC506, 33FJ128MC510, 33FJ128MC706, 33FJ128MC708,
33FJ128MC710, 33FJ128MC802, 33FJ128MC804,
33FJ256GP506, 33FJ256GP510, 33FJ256GP710,
33FJ256MC510, 33FJ256MC710,
33EP32GP502, 33EP32GP503, 33EP32GP504,
33EP32MC202, 33EP32MC203, 33EP32MC204, 33EP32MC502, 33EP32MC503, 33EP32MC504,
33EP64GP502, 33EP64GP503, 33EP64GP504, 33EP64GP506,
33EP64MC202, 33EP64MC203, 33EP64MC204, 33EP64MC206, 33EP64MC502, 33EP64MC503, 33EP64MC504, 33EP64MC506,
33EP128GP502, 33EP128GP504, 33EP128GP506,
33EP128MC202, 33EP128MC204, 33EP128MC206, 33EP128MC502, 33EP128MC504, 33EP128MC506,
33EP256GP502, 33EP256GP504, 33EP256GP506,
33EP256MC202, 33EP256MC204, 33EP256MC206, 33EP256MC502, 33EP256MC504, 33EP256MC506,
33EP512GP502, 33EP512GP504, 33EP512GP506,
33EP512MC202, 33EP512MC204, 33EP512MC206, 33EP512MC502, 33EP512MC504, 33EP512MC506,
AT90S1200, AT90S2313,
AT90S8515, AT90S8535, ATmega48, ATmega8, ATmega88, ATmega8515,
ATmega8535,
ATmega16, ATmega164,
ATmega168, ATmega32, ATmega324,
ATmega328, ATmega64,
ATmega644, ATmega1284,
ATtiny11,
ATtiny12, ATtiny13,
ATtiny2313, ATtiny24, ATtiny25,
ATtiny26, ATtiny261, ATtiny4313,
ATtiny44, ATtiny45,
ATtiny461, ATtiny48,
ATtiny84, ATtiny85, ATtiny88, ATtiny861,
2400, 2401, 2402, 2404, 2408, 2416, 2432, 2464, 24128, 24256, 24512, 241024,
241025,
25010, 25020, 25040, 25080, 25160, 25320, 25640, 25128, 25256, 25512,
251024,
95010, 95020, 95040, 95080, 95160,
95320, 95640, 95128, 95256, 95512, 95M01, 95M02,
251005, 252005,
254005, 258005,
251605,
25X05, 25X10, 25X20,
25X40, 25X80, 25X16, 25X32, 25X64, 25X128,
25Q40,
93S46,
93x46, 93x46A,
93S56, 93x56, 93x56A, 93S66,
93x66, 93x66A, 93x76, 93x76A, 93x86, 93x86A,
DS2430, DS2431, DS2433, DS28EC20,
DS1820,
11010, 11020, 11040, 11080, 11160
supporto in sola lettura:
12C671, 12C672,
12CE673, 12CE674
Importante!! I dispositivi a 3,3V non devono essere usati senza le espansioni a 3,3V, pena danni irreparabili;
il programma verifica la presenza di questi adattatori prima di iniziare a programmare, ma ovviamente bisogna
fare attenzione a selezionare il dispositivo giusto; i dispositivi a 3,3V sono:
12F1xxx,16F1xxx,18FxxJxx,18FxxKxx,24Fxxx,24Hxxx,33Fxxx.
Alcuni di questi hanno varianti che funzionano anche a 5V; se è necessario programmarli a 5V bisogna usare l'opzione
"Non richiedere espansioni LV".
Un altro errore da evitare è inserire i 24F-33F nello zoccolo per 30F, che funziona a 5V.
Protocollo di comunicazione
Nella scelta del protocollo di comunicazione bisogna tenere conto di varie esigenze fra loro spesso contrastanti:
velocità ed efficienza di trasferimento, dimensione del codice, universalità ed espandibilità.
Rispetto a un collegamento seriale, quello USB ha la peculiarità di essere basato su pacchetti dati;
si considera che i dati in un pacchetto arrivino contemporaneamente al dispositivo.
Nel caso di periferiche HID non se ne possono spedire più di uno ogni ms, quindi non è possibile gestire
le temporizzazioni in maniera diretta come con una seriale, e si devono introdurre dei comandi che,
opportunamente espansi dal microcontrollore, ricreano le forme d'onda desiderate.
D'altronde uno degli obiettivi di un programmatore affidabile è quello di essere indipendente dalla velocità del
PC e dal suo carico di lavoro, per cui il compito di generare le forme d'onda precise deve ricadere comunque sul
microcontrollore.
Dunque esistono a un estremo i programmatori seriali semplici, che ricevono solo comandi per forzare i livelli
di tensione:
il software sul PC controlla sia le temporizzazioni che l'algoritmo di programmazione, occupando però completamente
la CPU e risentendo pesantemente degli altri programmi in esecuzione.
All'opposto i programmatori "intelligenti" generano le temporizzazioni e gestiscono gli algoritmi,
ma devono essere aggiornati per supportare nuovi dispositivi; inoltre visto il numero di algoritmi
esistenti l'occupazione di memoria sarà alta.
Qui la scelta è caduta su un sistema ibrido: nel firmware sono stati implementati i comandi elementari ICSP
(In Circuit Serial Programming), ma gli algoritmi sono gestiti dal software.
Per aumentare la velocità e l'efficienza di trasferimento ci sono alcune istruzioni che corrispondono a comandi
ripetuti molto spesso, ad esempio le letture sequenziali, o a combinazioni di istruzioni.
Il vantaggio di questo approccio è che le temporizzazioni sono molto precise perchè gestite dal microcontrollore,
ma allo stesso tempo la grande varietà di algoritmi viene implementata nel software e non aumenta la dimensione
del codice firmware.
Un ulteriore vantaggio è che una volta verificati i comandi base del firmware tutto lo sviluppo degli algoritmi
si può fare su PC, in maniera certamente più veloce e senza dover aggiornare continuamente il firmware.
Per esempio per entrare in program mode col 16F628 e leggere DevID la sequenza sarebbe:
SET_PARAMETER //imposto i ritardi che verranno usati dalle altre istruzioni
SET_T1T2 //codice per modificare T1 e T2
1 //T1=1us
100 //T2=100us
EN_VPP_VCC //Vpp e Vcc a 0
0x0
SET_CK_D //Clock e Dato in uscita a 0
0x0
EN_VPP_VCC //abilito Vpp
0x4
NOP //piccolo ritardo
EN_VPP_VCC //abilito Vdd+Vpp
0x5
NOP //piccolo ritardo
LOAD_CONF //contatore a 0x2000
0xFF //config fasulla
0xFF //config fasulla
INC_ADDR_N //incrementol'indirizzo di 6
0x06
READ_DATA_PROG //leggo DevID
...
Oltre ai comandi ICSP ci sono istruzioni che permettono di gestire il programmatore,
le tensioni di programmazione, imporre ritardi precisi, comunicare via I2C e SPI.
Ogni istruzione dura almeno 40us, dovuti al ciclo di esecuzione dell'interprete;
i comandi ICSP sono temporizzati in base ai parametri T1-T2 o a quanto scritto nei
documenti Microchip; tutte fanno almeno un eco sul pacchetto di ritorno, eccetto FLUSH
che svuota la coda di uscita e la spedisce subito in un pacchetto di 64 byte.
Nel caso non ci siano i parametri richiesti da un comando, viene restituito 0xFE e termina l'esecuzione del pacchetto.
Lo stato della comunicazione USB è segnalato dal LED2: lampeggia a 4 Hz durante l'enumerazione,
a 1 Hz quando la comunicazione è normale.
Il LED1 invece segnala quando ci sono istruzioni in esecuzione.
L'elenco completo delle istruzioni:
Comando |
Valore |
Parametri |
Risposta |
Note |
NOP |
0x00 |
no |
eco |
non fa nulla |
PROG_RST |
0x01 |
no |
eco + 10B |
reset del programmatore; spedisce versione fw. (3B), ID(3B), la stringa " RST" |
PROG_ID |
0x02 |
no |
eco + 6B |
spedisce versione fw. (3B), ID (3B) |
CHECK_INS |
0x03 |
1B |
eco + 1B |
se l'istruzione specificata nel parametro esiste ne
rispedisce il codice, altrimenti invia errore (0xFE) |
FLUSH |
0x04 |
no |
nessuno |
svuota la coda di uscita (invia 64B) e ferma l'interprete comandi per il pacchetto corrente |
VREG_EN |
0x05 |
no |
eco |
accende il regolatore di tensione |
VREG_DIS |
0x06 |
no |
eco |
spegne il regolatore di tensione |
SET_PARAMETER |
0x07 |
1B |
eco |
imposta parametri interni (di ritardo o altro); byte1
parametro da cambiare, byte 2-3 valore:
SET_T1T2 (=0): T1 e T2
SET_T3 (=1): T3(H,L)
SET_timeout (=2): timeout(H,L)
SET_MN (=3): M,N |
WAIT_T1 |
0x08 |
no |
eco |
ritardo di T1 us (=1us all'avvio) |
WAIT_T2 |
0x09 |
no |
eco |
ritardo di T2 us (=100us all'avvio) |
WAIT_T3 |
0x0A |
no |
eco |
ritardo di T3 us (=2ms all'avvio) |
WAIT_US |
0x0B |
1B |
eco |
ritardo variabile di N us |
READ_ADC |
0x0C |
no |
eco +2B |
legge la tensione del regolatore (10bit efficaci,MSB-LSB);
considerato il partitore in ingresso la tensione in Volt si ricava come
<valore>/1024*5*34/12 |
SET_VPP |
0x0D |
1B |
eco +1B |
imposta la tensione del regolatore a <parametro>/10;
se entro 15ms l'errore di tensione è < 200mV rispedisce
<parametro>, altrimenti errore (0xFE) |
EN_VPP_VCC |
0x0E |
1B |
eco |
controlla Vpp e Vcc del dispositivo da programmare;
1 bit controlla il livello (0-1), 1bit l'impedenza (lasciare a 0)
bit 0-1: Vcc, bit 2-3: Vpp |
SET_CK_D |
0x0F |
1B |
eco |
controlla le linee CK, D, PGM del dispositivo da
programmare; 1 bit controlla il livello (0-1), 1bit l'impedenza
(bassa-alta); bit 0-1: D, bit 2-3: CK, bit 4-5: PGM |
READ_PINS |
0x10 |
no |
eco +1B |
legge lo stato delle linee di controllo e
comunicazione, 1 bit livello (0-1), 1bit impedenza (bassa-alta);
bit 0-1: D, bit 2-3: CK, bit 4-5: PGM |
LOAD_CONF |
0x11 |
2B |
eco |
Comando ICSP: Load configuration (000000), T1 us tra
comando e dati; 14 bit dati (allineati a destra, MSB-LSB) |
LOAD_DATA_PROG |
0x12 |
2B |
eco |
Comando ICSP: Load Data in Program Memory (000010), T1
us tra comando e dati; 14 bit dati (allineati a destra, MSB-LSB) |
LOAD_DATA_DATA |
0x13 |
1B |
eco |
Comando ICSP: Load Data in Data Memory (000011), T1 us tra comando e dati; 8 bit dati |
READ_DATA_PROG |
0x14 |
no |
eco +2B |
Comando ICSP: Read Data from Program Memory (000100),
T1 us tra comando e dati; 14 bit dati (allineati a destra, MSB-LSB) |
READ_DATA_DATA |
0x15 |
no |
eco +1B |
Comando ICSP: Read Data from Data Memory (000101), T1 us tra comando e dati; 8 bit dati |
INC_ADDR |
0x16 |
no |
eco |
Comando ICSP: Increment Address (000110), ritardo di T1 us alla fine |
INC_ADDR_N |
0x17 |
1B |
eco |
Comando ICSP: Increment Address (000110), ritardo di T1 us alla fine; ripetuto N volte |
BEGIN_PROG |
0x18 |
no |
eco |
Comando ICSP: Begin Programming (001000) |
BULK_ERASE_PROG |
0x19 |
no |
eco |
Comando ICSP: Bulk Erase Program Memory (001001) |
END_PROG |
0x1A |
no |
eco |
Comando ICSP: End Programming (001010) |
BULK_ERASE_DATA |
0x1B |
no |
eco |
Comando ICSP: Bulk Erase Data Memory (001011) |
END_PROG2 |
0x1C |
no |
eco |
Comando ICSP: End Programming (001110) |
ROW_ERASE_PROG |
0x1D |
no |
eco |
Comando ICSP: Row Erase Program Memory (010001) |
BEGIN_PROG2 |
0x1E |
no |
eco |
Comando ICSP: Begin Programming (0011000) |
CUST_CMD |
0x1F |
1B |
eco |
Comando ICSP specificato nel parametro |
PROG_C |
0x20 |
2B |
eco +1B |
Programma word seguendo l'algoritmo per 12Cxxx: 000010,
001000, 001110, M pulses & N overpulses |
CORE_INS |
0x21 |
2B |
eco |
Comando ICSP PIC18: Core instruction (0000); 16 bit dati (MSB-LSB) |
SHIFT_TABLAT |
0x22 |
no |
eco +1B |
Comando ICSP PIC18: Shift TABLAT (0010); 8 bit dati |
TABLE_READ |
0x23 |
no |
eco +1B |
Comando ICSP PIC18: Table read (1000); 8 bit dati |
TBLR_INC_N |
0x24 |
1B |
eco+N+NB |
Comando ICSP PIC18: Table read post-inc (1001); 8 bit
dati; ripete N volte; rispedice N e NB dati |
TABLE_WRITE |
0x25 |
2B |
eco |
Comando ICSP PIC18: Table write (1100); 16 bit dati (MSB-LSB) |
TBLW_INC_N |
0x26 |
(2N+1)B |
eco |
Comando ICSP PIC18: Table write post-inc
(1101); 16 bit dati (MSB-LSB); ripete N volte (N è il primo parametro) |
TBLW_PROG |
0x27 |
4B |
eco |
Comando ICSP PIC18: Table write and program (1111); 16
bit dati (MSB-LSB); di seguito esegue un NOP con ritardo di scrittura
specificato dal parametro 3-4 (in us) |
TBLW_PROG_INC
|
0x28 |
4B |
eco |
Comando ICSP PIC18: Table write and program post-inc (1110); 16
bit dati (MSB-LSB); di seguito esegue un NOP con ritardo di scrittura
specificato dal parametro 3-4 (in us) |
SEND_DATA |
0x29 |
3B |
eco |
Comando ICSP PIC18 specificato nel byte 1; scrive 16 bit dati (MSB-LSB) |
READ_DATA |
0x2A |
1B |
eco+1B |
Comando ICSP PIC18 specificato nel byte 1; legge 8 bit dati |
I2C_INIT |
0x2B |
1B |
eco |
Inizializza la periferica I2C: 0xFF disabilita I2C;
bit 6: controllo slew per velocità > 100kbps;
bit 5:3 velocità: 0=100k, 1=200k, 2=400k, 3=800k, 4=1M;
attenzione: usare resistenze di pull-up adatte alla velocità scelta;
bit 2:0: livello logico delle linee A2-A1-A0 del dispositivo |
I2C_READ |
0x2C |
3B |
eco+1+NB |
Legge <parametro 1> byte dal bus I2C usando il byte di controllo
<parametro 2> e l'indirizzo <parametro 3>; forza automaticamente il bit
RW del byte di controllo. Risponde con <parametro 1> + Dati o
ACK_ERR (0xFD) in caso di errore di acknowledge (ad es. se non ci sono
dispositivi connessi) |
I2C_WRITE |
0x2D |
3B+NB |
eco |
Scrive <parametro 1> byte sul bus I2C usando il byte di controllo
<parametro 2> e l'indirizzo <parametro 3>;
forza automaticamente il bit RW del byte di controllo.
Risponde (0xFD) in caso di errore di acknowledge (ad es.
se non ci sono dispositivi connessi).
In caso di indirizzi a 2 byte è sufficiente usare il secondo byte di
indirizzo come primo dei dati. |
I2C_READ2 |
0x2E |
4B |
eco+1+NB |
Legge dal bus I2C; come I2C_READ, ma usa 2 byte per gli indirizzi |
SPI_INIT |
0x2F |
1B |
eco |
Inizializza la periferica SPI: 0xFF disabilita SPI;
bit 1:0 velocità: 0=100kbps, 1=200kbps, 2=300kbps, 3=500kbps;
bit 2:3 modo SPI |
SPI_READ |
0x30 |
1B |
eco+1+NB |
Legge <parametro 1> byte dal bus SPI. Risponde con <parametro 1> + Dati
Se <parametro 1>=0 risponde col byte ricevuto durante l'ultimo trasferimento (lettura o scrittura) |
SPI_WRITE |
0x31 |
1B+NB |
eco+1B |
Scrive <parametro 1> byte sul bus SPI. |
EXT_PORT |
0x32 |
2B |
eco |
Forza i livelli delle porte di comunicazione:
<parametro 1> = <RB7:RB0> <parametro 2> = <RC7,RC6,RA5:RA3>
Non modifica la direzione dei segnali. |
AT_READ_DATA |
0x33 |
3B |
eco+1+2NB |
Comando ATMEL: read program memory (0010H000); legge <parametro 1> word
all'indirizzo <parametro 2> : <parametro 3>
via SPI. Risponde con <parametro 1> + Dati |
AT_LOAD_DATA |
0x34 |
3B+2N |
eco+1B |
Comando ATMEL: load program memory page (0100H000); carica <parametro 1>
word all'indirizzo <parametro 2> : <parametro 3>
via SPI. Risponde con <parametro 1> |
CLOCK_GEN |
0x35 |
1B |
eco |
Genera un clock su RB3 (tramite CCP1-2 e TIMER1)
bit 2:0 frequenza: 0=100kHz, 1=200kHz, 2=500kHz, 3=1MHz, 4=2MHz, 5=3MHz, 6=6MHz;
Disabilita l'uscita PWM1 (regolatore DCDC).
|
SIX |
0x36 |
3B |
eco |
Comando ICSP PIC24: Core instruction (0000); 24 bit dati (MSB-LSB) |
REGOUT |
0x37 |
no |
eco +2B |
Comando ICSP PIC24: Shift out VISI register (0001); 16 bit dati (MSB-LSB)) |
ICSP_NOP |
0x38 |
no |
eco |
Comando ICSP PIC24: esegue NOP (0000) |
TX16 |
0x39 |
1B+2NB |
eco+1B |
Trasmette N*16 bit via ICSP (MSB-LSB); periodo di clock: 2*(T1-1)+1 us |
RX16 |
0x3A |
1B |
eco+1+2NB |
Riceve N*16 bit via ICSP (MSB-LSB); periodo di clock: 2*(T1-1)+1 us |
uW_INIT |
0x3B |
no |
eco |
Inizializza la comunicazione MicroWire |
uW_TX |
0x3C |
1B+NB |
eco |
Scrive <parametro 1> bit sul bus MicroWire |
uW_RX |
0x3D |
1B |
eco+1+NB |
Legge <parametro 1> bit dal bus MicroWire |
SIX_LONG |
0x3E |
3B |
eco |
Comando ICSP PIC24: Core instruction (0000); 24 bit dati (MSB-LSB); aggiunge 2 ICSP_NOP alla fine |
SIX_N |
0x3F |
1B+3NB |
eco |
Comando ICSP PIC24: Core instruction (0000); N * 24 bit dati (MSB-LSB); invia N istruzioni e
aggiunge M ICSP_NOP dopo ognuna; N=<parametro1>&0x3F, M=<parametro1> >> 6 |
OW_RESET |
0x40 |
no |
eco+1B |
Reset del bus OneWire; rileva impulso di presenza: 1=presente 0=assente |
OW_WRITE |
0x41 |
1B+NB |
eco |
Scrive <parametro 1> byte sul bus OneWire |
OW_READ |
0x42 |
1B |
eco+1+NB |
Legge <parametro 1> byte dal bus OneWire |
UNIO_STBY |
0x43 |
no |
eco |
Genera un impulso di standby UNIO |
UNIO_COM |
0x44 |
1B+1B+NB |
eco+1+NB |
Esegue una comunicazione UNIO: scrive <parametro 1> byte e
legge <parametro 2> byte; genera un byte di sincronizzazione
se ci sono byte da scrivere |
SET_PORT_DIR |
0x45 |
2B |
eco |
Forza la direzione delle porte di comunicazione (0=out, 1=in):
<parametro 1> = <RB7:RB0> <parametro 2> = <RC7,RC6,RA5:RA3> |
READ_B |
0x46 |
no |
eco+1B |
Legge lo stato della porta B |
READ_AC |
0x47 |
no |
eco+1B |
Legge lo stato delle porte A e C:
<RC7,RC6,RA5:RA3> |
AT_HV_RTX |
0x48 |
1B+2NB |
eco+1B |
Trasmette 2N*8 bit su RB0/RC7 (PB1/PB0), CLK su RC6 (PB3)
byte N=PB1, byte N+1=PB0
Riceve 8 bit da RB1 (PB2) (solo l'ultimo byte) |
SIX_LONG5 |
0x49 |
3B |
eco |
Comando ICSP PIC24: Core instruction (0000); 24 bit dati (MSB-LSB); aggiunge 5 ICSP_NOP alla fine |
LOAD_PC |
0x50 |
2B |
eco |
Comando ICSP: Load PC address (011101), T1 us tra comando e dati; 16 bit dati (allineati a destra, MSB-LSB) |
LOAD_DATA_INC |
0x51 |
2B |
eco |
Comando ICSP: Load data in NVM memory and increase address (100010), T1 us tra comando e dati;
14 bit dati (allineati a destra, MSB-LSB) |
READ_DATA_INC |
0x52 |
no |
eco+2B |
Comando ICSP: Read data from NVM memory and increase address (100100), T1 us tra comando e dati;
14 bit dati (allineati a destra, MSB-LSB) |
JTAG_SET_MODE |
0x53 |
1B |
eco |
JTAG SET MODE: 6 bit dati |
JTAG_SEND_CMD |
0x54 |
1B |
eco |
JTAG COMMAND: 5 bit dati |
JTAG_XFER_DATA |
0x55 |
4B |
eco+4B |
JTAG TRANSFER DATA: 32 bit dati MSB-LSB |
JTAG_XFER_F_DATA |
0x56 |
4B |
eco+4B |
JTAG TRANSFER FAST DATA: 32 bit dati MSB-LSB |
ICSP8_SHORT |
0x57 |
1B |
eco |
Comando ICSP 8-bit senza dati: codice in <parametro1> |
ICSP8_READ |
0x58 |
1B |
eco+2B |
Comando ICSP 8-bit con lettura dati a 16 bit: codice in <parametro1> |
ICSP8_LOAD |
0x59 |
3B |
eco |
Comando ICSP 8-bit con scrittura dati a 16 bit: codice in <parametro1> |
READ_RAM |
0xF0 |
2B |
eco+3B |
Legge dalla memoria del micro di controllo; indirizzo a
16 bit, dato 8 bit; fa eco dell'indirizzo |
WRITE_RAM |
0xF1 |
3B |
eco+3B |
Scrive sulla memoria del micro di controllo; indirizzo
a 16 bit, dato 8 bit; fa eco dell'indirizzo e del dato |
LOOP |
0xF2 |
no |
no |
Riporta il puntatore istruzioni a 0 ed riesegue tutte le istruzioni ricevute.
Il micro non accetta più altri comandi. Solo per esigenze di test. |
Schema elettrico (v2.1)
La funzionalità del programmatore dipende da due sezioni distinte: la parte di comunicazione USB
e la parte di generazione delle tensioni di programmazione.
Per quanto riguarda la periferica USB sono necessari veramente pochi componenti oltre al micro principale: il quarzo,
qualche condensatore, qualche resistenza e il connettore USB tipo B (anche micro-B), tutto
come da Application Note della Microchip.
La sezione che si occupa delle ensioni richiede una serie di linee IO digitali, delle alimentazioni selezionabili, e un generatore
ad alta tensione implementato con un
convertitore DCDC step-up a tensione variabile (Q4, L1, D3), descritto di seguito.
Inoltre servono tre transistor per controllare VDDU e VPPU.
Il micro principale è un PIC18F2550 o un 18F25K50, a 28 piedini; nel caso 25K50 non serve il quarzo né C2-C3.
Altro vantaggio del 25K50 è che si può programmare a bassa tensione, quindi basta un programmatore ricavato da un Arduino o un ESP8266.
Invece il 18F2553 differisce per l'ADC a 12 bit e quindi richiede la ricompilazione del firmware.
Volendo usare i modelli a 40 piedini corrispondenti (4550,45K50,4553) bisognerebbe modificare
il circuito tenendo fissi gli assegnamenti delle porte; le ulteriori risorse disponibili rimarrebbero inutilizzate.
Lo
schema elettrico è disegnato con
KiCad; qua sotto il modulo base:
Molti componenti sono opzionali, servono solo per programmare alcuni tipi dispositivi o per agganciare ulteriori schede di espansione:
i connettori CONN2-3-4-5-6, le resistenze di protezione R11:23,
le resistenze di pull-up I2C R26-27, il pulsante S1, lo zoccolo per memorie I2C.
Elenco componenti:
- U1 quarzo 12Mhz (non necessario quando si usa il 25K50; anche 4, 8, 16, 20 MHz: in tal caso bisogna riconfigurare il divisore nel micro)
- U2 18F2550 o 18F25K50 (anche 2553,4550,45K50,4553, vedi sopra)
- U3 zoccolo 20p.
- U4 zoccolo 8p.
- Q1-Q2 BC557 (o qualsiasi PNP, attenzione al montaggio)
- Q3-Q4 BC547 (o qualsiasi NPN, attenzione al montaggio)
- D1-D2 LED a piacere
- D3 1N4148 (o qualsiasi diodo, meglio se Shottky)
- L1 100µH (tipo resistenza o altro)
- R1 22KΩ
- R2 12KΩ
- R3 100KΩ
- R4:6 10KΩ
- R7 1MΩ
- R8-R9 2.2KΩ
- R10 3.3KΩ
- R11:23 100Ω
- R24-R25 330KΩ
- R26-R27 10KΩ
- C1 22-100µF 25V
- C2-C3 22pF
- C4 >= 220nF
- C5 100nF
- C6 10µF
- C7-C8 100nF
- CONN1 USB tipo B o in alternativa CONN1B1 tipo micro-USB-B
- CONN2-3 connettori a pettine femmina 10 poli
- CONN4-5 connettori a pettine maschio 5 poli
- CONN6 connettore a pettine femmina 3 poli
Nel montaggio bisogna fare attenzione all'orientamento dei transistor:
Q1 ha l'emettitore a sinistra, Q2 in alto, Q3 e Q4 a destra.
Un circuito funzionante, una volta connesso al PC, fa lampeggiare il led D2 a 4Hz fino a quando non termina
l'enumerazione, e successivamente a 1Hz.
Tramite i due connettori CONN2-3 si possono poi collegare varie schede di espansione:
- per PIC a 28-40 piedini
- per PIC 8-20p. (come sulla scheda base, ma c'è più spazio per montare uno zoccolo ZIF)
- per PIC16-18 a 3,3V (questo adattatore ha anche un regolatore a 3,3V)
- per PIC24-30-33 (questo adattatore ha anche un regolatore a 3,3V)
- per Memorie I2C, SPI, MicroWire
- per Memorie SPI a 3,3V (questo adattatore ha anche un regolatore a 3,3V)
- per ATMEL AVR a 8-14-20-28-40p.
I componenti per le schede di espansione sono indicati nello
schema elettrico completo;
i diodi possono essere di qualunque tipo; le resistenze TBD non vanno montate.
Sulle schede di espansione consiglio di inserire i pettini di dal lato componenti facendoli spuntare sotto
e di lasciare il distanziatore plastico sopra; questo aumenta molto la resistenza meccanica, soprattutto in fase di estrazione.
Dopo il montaggio bisogna verificare il corretto funzionamento eseguendo la funzione "test hardware" nel programma di controllo (OP o OPGUI).
In questa modalità, da eseguire senza dispositivi da programmare, vengono attivate in varie combinazioni le uscite
CK, D, PGM, VDDU, VPPU, presenti sui piedini 14-15-12-1-4 di U3 (le tensioni sono riferite a GND, piedino 5). Se la tensione misurata
corrisponde a quanto dice il programma vuol dire che il circuito è funzionante.
La tensione VPP può non corrispondere esattamente a quella impostata, e avere errori anche di +-1V; questo è dovuto
al fatto che il riferimento di tensione del convertitore DCDC è la VCC stessa, che viene fornita dal cavo USB e può
variare da 4.75V a 5.25V; inoltre il partitore R1-R2 può introdurre un ulteriore errore del 5%.
Tra le cause più frequenti di malfunzionamento (vero o presunto) ci sono:
orientamento scorretto dei transistor,
induttanza di valore errato,
difetti nel pcb come corti tra piste o piste aperte,
condensatori staccati o di valore errato,
microcontrollore principale non programmato o programmato male (spesso con config word sbagliata, ovvero con opzione LVP).
Qui si trova il progetto completo.
Questo
è invece l'archivio della vecchia versione disegnata con
gEDA.
PCB
Il circuito stampato è stato ottimizzato per essere prodotto in casa, quindi usa una sola faccia più alcuni ponticelli sul lato componenti,
(inutili ovviamente nel caso PCB a doppia faccia). Le tracce sono piuttosto spesse tranne in alcuni punti critici.
Il connettore micro-USB SMD è consigliato solo se si usa un PCB a doppia faccia.
Per produrlo da un fornitore commerciale ci vogliono i file gerber; nell'archivio degli schemi si trovano anche questi,
ma conteneti sia la scheda base che tutte le espansioni. Qualora non servissero tutte si dovrebbero ri-generare i file gerber
dopo aver cancellato quello che non serve.
Novità della versione 2.0 è lo spostamento di uno dei connettori di espansione di 50 mil in basso, così da eliminare la possibilità di
inserire le espansioni al contrario.
Anche i circuiti stampati (dalla 2.0) sono disegnati con
KiCad.
Qui sotto il modulo base:
Chi avesse la pazienza può anche fare a meno dello stampato e montare il tutto su millefori.
Per chi invece volesse il PCB della scheda base già fatto ho creato un
progetto shared su PCBWay (ovviamente non obbligatorio!)
Come si usa
La scheda base può ospitare i PIC a 8,14,18,20 piedini (eccetto i 10Fxxx).
Tutti vanno inseriti in U3 allineati al piedino 1 (stesso discorso per i dispositivi nelle schede di espansione):
In U4 vengono ospitate le memorie EEPROM I2C e UNIO.
I dispositivi OneWire (TO92) si connettono su CONN6.
Per i 10Fxxx a 6 o 8 piedini ci vuole un adattatore (non fornito).
Alcuni dispositivi richiedono una tensione massima di 3,3V che viene fornita da un regolatore presente in alcune delle schede di espansione.
Il software verifica la presenza di questi adattatori (che hanno RB1 in corto con RB0) per evitare danni irreparabili.
In alcuni casi (e.g 16F1x o 18F), solo la versione LF ha questa limitazione, ma il controllo sulla 3,3V è presente per tutte le versioni
(per sicurezza, visto che la già lunga lista di dispositivi non comprende le varie sotto-versioni di ogni modello).
Nei software è comunque disponibile una opzione per disabilitare questo controllo.
La programmazione "in circuit" (ossia senza staccare il dispositivo dal suo circuito applicativo)
si ottiene collegando il connettore ICSP alla scheda applicativa tramite cavo.
I dispositivi a 3,3V richiedono una interfaccia ICSP anch'essa a bassa tensione, presente sulle schede di espansione a 3,3V.
Il connettore ICSP-IN del modulo base serve invece per programmare il micro principale senza toglierlo, mediante un altro programmatore.
Le immagini seguenti mostrano dove inserire i dispositivi sulle varie schede:
Come programmare il micro la prima volta?
E' un problema molto interessante, visto che un dispositivo nuovo è vuoto e non funziona come micro principale del programmatore;
ci sono varie possibilità:
- farlo programmare da qualcuno che ce ha già un programmatore funzionante o un PICKIT.
- Disponendo di una RS232, costruire un programmatore seriale come il JDM,
magari su millefori, e come software winpic o picprog.
- Avendo scelto il 25K50, usare un programmatore basato su Arduino o ESP8266 o simili.
- Ordinarlo pre-programmato dalla MICROCHIP.
- Se proprio non sapete come fare potete contattami e ve lo posso programmare io.
Potrebbe sembrare strano dover costruire un programmatore per farne un altro, ma
non c'è modo di comunicare via USB senza firmware; credo però che ne
valga la pena, visto che i programmatori seriali non sono molto
affidabili, sono lenti, e soprattutto non si possono usare sui nuovi computer.
Un consiglio: assicuratevi di aver programmato bene il dispositivo (tramite verifica); se usate un 2550 evitate assolutamente
di abilitare la programmazione LVP (a bassa tensione); questa infatti riserva RB5 per entrare in program mode
e RB6-RB7 per comunicare, col risultato che il circuito comunica via USB ma non funziona; ciò in pratica esclude i programmatori a bassa tensione.
Inoltre, visto che attualmente non c'è un bootloader,
consiglio di tenere un micro di scorta per caricare le versioni aggiornate del firmware.
Mappa delle risorse e dei connettori:
Pin |
Funzioni varie |
ICSP |
I2C-EEPROM |
SPI-EEPROM |
SPI-ATMEL |
uW-EEPROM |
OneWire/UNIO |
RB7 |
|
PGM |
|
|
|
|
|
RB6 |
|
ICSP clock |
|
|
|
|
|
RB5 |
|
ICSP data |
A2 |
|
|
W (6) |
|
RB4 |
|
|
A1 |
HLD |
|
S (1) |
|
RB3 |
|
|
A0 |
CS |
Device clock |
PRE (7) |
|
RB2 |
espansione |
|
|
|
|
|
|
RB1 |
|
|
Clock |
Clock |
SPI Clock |
Clock |
|
RB0 |
|
|
Data |
Data out (MISO) |
Data out (MISO) |
Data out |
Data IO |
RC7 |
|
|
|
Data in (MOSI) |
Data in (MOSI) |
Data in |
|
RC6 |
|
|
WP |
WP |
RESET |
|
|
RC5 |
USB D+ |
|
|
|
|
|
|
RC4 |
USB D- |
|
|
|
|
|
|
RC2 |
DCDC PWM |
|
|
|
|
|
|
RC1 |
controlla VDD |
|
|
|
|
|
|
RC0 |
controlla VPP |
|
|
|
|
|
|
RA5 |
espansione |
|
|
|
|
|
|
RA4 |
espansione |
|
|
|
|
|
|
RA3 |
espansione |
|
|
|
|
|
|
RA2 |
LED 2 |
|
|
|
|
|
|
RA1 |
LED 1 |
|
|
|
|
|
|
RA0 |
ADC per regolatore |
|
|
|
|
|
|
RE3 |
Pulsante S1 |
|
|
|
|
|
|
Qualche foto delle varie schede:
Base + espansione montata:
Dispositivo OneWire (TO92) collegato su una vecchia versione priva di connettore dedicato:
Regolatore DCDC boost
Per generare una tensione Vpp maggiore di 5V bisogna usare un convertitore DCDC a commutazione di tipo boost.
In commercio ne esistono a migliaia, ma seguendo la filosofia del minimo
indispensabile ne ho realizzato uno col micro stesso, al modico costo
di un transistor e qualche componente passivo.
Caratteristica molto importante richiesta in questo progetto è di poter variare la tensione
di uscita durante il funzionamento.
Per tenerla fissa nelle diverse condizioni operative bisogna poi variare
la larghezza degli impulsi di commutazione in funzione del valore ottenuto.
In pratica si tratta di realizzare un regolatore con anello di reazione digitale,
come illustrato nello schema seguente.
I blocchi di base ci sono tutti: periferica PWM, convertitore A/D, DSP(quasi).
Attualmente il convertitore A/D usa come riferimento l'alimentazione a 5V, quindi l'uscita varia
in funzione di questa; è però possibile collegare un riferimento esterno su RA3 e migliorare la
precisione.
La frequenza di commutazione è 90 kHz, ben oltre la frequenza di taglio del filtro LC
in uscita (~2,3 kHz).
Le prestazioni in corrente sono limitate dalle perdite del transistor,
del diodo, dell'induttore, ma visto che l'assorbimento del carico è basso si può
usare un comunissimo diodo al silicio, un transistor NPN qualsiasi, e
un induttore a goccia; per migliorare il comportamento si può optare
per un diodo Shottky, tipo BAT41, un transistor più grosso
(o un Mosfet) e un'induttanza avvolta in aria.
Rimane da progettare un regolatore (blocco C) opportuno: è meglio lavorare nel dominio s,
quindi serve modello alle variazioni del convertitore, cosa che
fortunatamente è stata già fatta e si trova un po' dappertutto, ad esempio
qui.
Con i componenti scelti il convertitore opera in regime discontinuo,
infatti la corrente critica risulta:
Icrit=Vu*T/(16*L)=86 mA
molto al di sopra del consumo effettivo, che supponiamo 1mA.
Parametri di calcolo:
Vi=5
Vu=12.5
D=(vu-vi)/vo
L=100e-6
C=47e-6
I=1e-3
R=12/I
Rl=1.6 (resistenza serie dell'induttore)
T=1/90e3
vu 1 vu M-1 Vu 2M -1
--- = Gdo ---------- dove Gdo = 2 --- ------- , M = ---, wp = ----------
D 1 + s/wp D 2M -1 Vi (M-1) RC
La funzione di trasferimento risulta:
vu 127.58
-- = -------------
D 0.22031 s + 1
Il diagramma di Bode è il seguente:
Dunque il sistema sarebbe stabile anche solo chiuso su se stesso, ma
avrebbe un errore a regime inversamente proporzionale al guadagno DC.
Per ovviare a questo bisogna inserire un controllore con un polo
nell'origine e uno zero più avanti per stabilizzare il tutto.
Ad esempio usando un controllore di questo tipo:
D 0.25 (s + 50)
C = --- = -------------
err s
la funzione di trasferimento si modifica come segue:
vu 144.77 s + 7238.4
-- = -----------------
vi s2 + 4.539 s
Si vede che il sistema rimane stabile, con margine di
fase ~75º.
Ora per chiudere l'anello di regolazione in digitale bisogna scegliere
la frequenza di campionamento.
Questa da un lato limita la banda passante del regolatore, dall'altra
viene limitata dalla potenza di calcolo del micro; un periodo di 250us
è risultato un buon compromesso.
Convertendo le varie funzioni di trasferimento nel dominio di z con la
trasformazione bilineare si ha:
vu 0.018199 z2+ 0.00022607 z - 0.017973
-- = ------------------------------------
vi z2 - 1.9989 z + 0.99887
Il regolatore è:
D 0.25156*z - 0.24844 C1 - C2 z-1
C = --- = ------------------- = -----------
err z - 1 1 -z-1
Ricordo che z
-1 rappresenta un ritardo di un
ciclo di clock.
Ora c'è da fare i conti con gli errori di quantizzazione e di calcolo.
Il convertitore A/D è a 10 bit e comadato dal Timer2; al termine
della conversione viene generato un interrupt e viene eseguita la
funzione di regolazione, che ha come uscita il nuovo duty-cycle del
generatore PWM, anch'esso a 10 bit.
Sul ramo di ritorno è necessario un partitore in modo da
limitare la tensione di ingresso all'intervallo [0,5V]; R1 e R2 hanno
questo compito.
Il diagramma del sistema si modifica come segue:
a=12/34
Vu=C'H(Vi-aVu)
Vu C'H
-- = ------
Vi 1+aC'H
Per ritornare al modello precedente moltiplichiamo ambo i membri per a
e poniamo il nuovo ingresso a Vi/a;
questo semplicemente comporterà una divisione del valore di tensione
desiderato.
Vu aC'H CH
---- = ------ = ----
Vi/a 1+aC'H 1+CH
aC'=C
aC1' - aC2' z-1 C1 - C2 z-1
aC'= --------------- = C = ------------
1 - z-1 1 - z-1
aC1'=C1
aC2'=C2
Visto che si lavora con rappresentazioni digitali a 10 bit vogliamo
passare da D/err a pwm/[err]
[err]=err*1024/5
pwm=D*1024
D pwm/1024 pwm C1' - C2'z-1
C'= --- = ------------ = ------- = ------------
err [err]/1024*5 [err]*5 1 -z-1
pwm(1 - z
-1)=[err](5*C1/a - 5*C2/a z
-1)=[err](3.564 - 3.52 z
-1)
E' chiaro che con moltiplicazioni fra interi non si riuscirebbe ad
avere una precisione accettabile sui coefficienti; la soluzione
più semplice è usare come uscita il risultato diviso per un
multiplo di 2
e ricalcolare i coefficienti di conseguenza.
Considerato che il registro pwm è allineato a sinistra risulta
semplicissimo dividere per 64, ossia tralasciare gli ultimi 6 bit.
pwm(1 - z
-1)=[err](k1 - k2 z
-1)/64
k1=5C1/a*64=228.12 ~ 228
k2=5C2/a*64=225.25 ~ 225
Di seguito le risposte al gradino del sistema continuo (blu), di quello
campionato con controllore ideale (rosso) e di quello con i
coefficienti reali (verde); come si vede coincidono tutte.
Il programma di calcolo
è Octave (ovviamente open
source), utilizzabile senza troppi
problemi anche col noto sistema (quasi)operativo a finestre.
Se qualcuno fosse interessato
questi
sono i listati dei modelli descritti prima.
Il codice effettivo della funzione di controllo è quasi tutto in
assembly: questo si è reso necessario per ridurre il tempo di
esecuzione; infatti il compilatore C inserisce una chiamata per ogni
moltiplicazione (che in questo caso è a 16 bit) con conseguenti
salvataggi delle variabili sullo stack; alla fine il tempo di
esecuzione arrivava a 50us, ossia una frazione significativa del
periodo.
In assembly invece si risparmiano le chiamate e si può fare
senza sprechi la moltiplicazione 16x8 bit (visti k1 e k2); alla fine il
tempo di esecuzione risulta 12us.
Qualche forma d'onda:
Transitorio di accensione (12V)
Risposta al variare della tensione regolata (da 8V a 9V)
Risposta al variare del carico (0-1mA e 1mA-0)
Come contribuire
Il modo migliore per contribuire a questo progetto è costruirlo, usarlo, e
segnalare eventuali bachi, idee, richieste di supporto.
In particolare rimangono da verificare parecchi dispositivi, vedi
supporto.
Chi avesse la pazienza e le conoscenze adatte può anche aggiungere altri algoritmi di
programmazione o altri comandi interni.
Oppure se vi avanza un dispositivo non supportato potete spedirmelo in modo che io lo possa provare.
Se trovate il progetto utile e lo usate scrivetemi due righe a
,
e se l'avete modificato mostratemi il vostro lavoro.
Su SourceForge sono presenti vari
forum
su cui discutere di questo progetto; oppure potete
racccomandarlo o lasciare un commento, spero positivo.
Scarica file
Schema elettrico e circuito stampato:
Pdf,
archivio completo
Firmware:
progetto MPLAB completo
o
firmware compilato per 18F2550(.hex)
oppure
firmware compilato per 18F25K50(.hex)
opgui (GTK GUI per Linux & Windows):
sorgenti
o
app Windows
OP (per linea di comando, Linux e Windows)
Guida all'uso di Opgui
Listati per Octave
Cronologia
in futuro | ampliare supporto PIC e AVR,aggiungere JTAG; ampliare supporto ICD; |
dicembre 2023 | opgui v0.12.2: corretta scrittura config sul 16F18456; aggiunto supporto per scheda all-in-one
|
febbraio 2023 | opgui v0.12.1: corretto crash quando si seleziona il filtro "*"
|
ottobre 2022 | firmware v0.12.0: adattato al 18F25K50;
opgui v0.12.0: aggiornamento alle librerie GTK3; nuova selezione dispositivo con lista; comandi manuali
op/opgui: aggiunti 16F15213-14-23-24-25-43-44-45-54-55-56-74-75-76,
16F18013-14-15-23-24-25-26-44-45-46-54-55-56-74-75-76,
16F18114-15-24-25-26-44-45-46-54-55-56-74-75-76,
16F17114-15-24-25-26-44-45-46-54-55-56-74-75-76,
18F04-05-06-14-15-16Q40-41,
18F24-25-26-44-45-46-54-55-56Q71,
18F26-27-46-47-56-57Q83-84;
corretta scrittura su 254005 |
dicembre 2021 | software v0.11.5: corretta scrittura config word su 33FJXX |
luglio 2021 | software v0.11.4: correzioni minori al codice |
aprile 2021 | software v0.11.3: corretta scrittura EEPROM su 16F184xx/188xx/191xx |
dicembre 2020 | circuiti v2.1: aggiunto pull-down su scheda espansione AVR |
ottobre 2020 | firmware v0.11.2: esteso ICSP8_READ fino a 16 bit (per i PIC18)
software v0.11.2: corretta scrittura 16F18xxx con spazio vuoto all'indirizzo 0;
aggiunti 18F25-26-27-45-46-47-55-56-57Q43,
18F25-26-27-45-46-47-55-56-57K42, 18F25-26K83;
[linux] cambiato percorso di accesso all'HW in /dev/hidraw
circuiti v2.0: porting su kicad; spostati connettori di espansione |
febbraio 2020 | software v0.11.1: corretto salvataggio file con 12F1XXX;
corretto timeout in scrittura config con 16F18XXX;
evita di leggere DIA-DCI con 16F188XX;
corretta verifica EE 0x22 con 18FXXX |
gennaio 2019 | firmware v0.11.0: aggiunte istruzioni ICSP8_SHORT,ICSP8_READ,ICSP8_LOAD;
software v0.11.0: aggiunti 16F15313-23-24-25-44-45-54-55-56-75-76-85-86,
16F18424-25-26-44-45-46-54-55-56,
16F18854-55-56-57-75-76-77,
16F19155-56-75-76-85-86-95-96-97 |
dicembre 2018 | software v0.10.1: aggiunti 16F1764-65-68-69-73-76-77-78-79;
rimosse funzioni MSVC6 |
giugno 2016 | firmware v0.10.0: aggiunte istruzioni LOAD_PC, LOAD_DATA_INC, READ_DATA_INC, JTAG_SET_MODE, JTAG_SEND_CMD, JTAG_XFER_DATA, JTAG_XFER_F_DATA;
nuovi VID&PID USB (0x1209,0x5432); modificati timing di alcuni clock; migliorato CLOCK_GEN;
software v0.10.0: aggiunti 16F18313-23-24-25-26-44-45-46; migliorata comunicazione USB |
novembre 2014 | software v0.9.1: vari miglioramenti all'interfaccia utente;
corretta verifica ATTiny11-12; corretta scrittura 24FJ128GA3xx-GB2xx-GCxx-DAxx;
aggiunti: forza configurazione per PIC18, test hardware linee IO,
velocità SPI automatica per AVR, scrivi AVR Fuse Low @ 3kHz;
verifica veloce per memorie FLASH SPI;
aggiunti 10F320-22,12F529T39A,12F752,12F1612-13-14-15-18-19,
16F1512-13,16F1574-75-78-79,16F1703-04-05-07-08-09-13-16-17-18-19,
16F1788-89,16F570,16LF1554-59,
18F24K50-25K50-26K50-45K50-46K50,
18F25K80-26K80-45K80-46K80-65K80-66K80,
18F63J11-90,18F64J11-90,18F65J10-11-15-50-90,
18F66J10-11-15-16-50-55-90-93,18F67J10-11-50-90-93,
18F83J11-90,18F84J11-90,18F85J10-11-15-50-90,
18F86J10-11-15-16-50-55-90-93,18F87J10-11-50-72-90-93,
25X128,25Q40 |
marzo 2014 | firmware v0.9.0: supporto ATMEL HV serial programming;
nuovo comando PIC24/33; migliorato regolatore DCDC;
software v0.9.0: Write16F72x richiede solo la config-word1;
aggiunto HV serial programming per ATtiny11-12-13-24-25-44-45-84-85;
aggiunti 24FJ64GA3xx-GCxx,24FJ128GA3xx-GB2xx-GCxx-DAxx,24FJ256DAxx,24EPx,33EPx;
aggiunti 95xx SPI EEPROM,25X05 FLASH;
aggiunti 12F1571-72,16F527,16F753,16F1454-55-59;
modifiche varie al codice; |
giugno 2013 | software v0.8.1: vari miglioramenti all'interfaccia utente;
corretta scrittura EEPROM quando è attiva la protezione codice/dati per 16F83-84,
12F629,12F675,16F627-28,16F630,16F676,16F870-1-2,16F873-74,16F876-77;
corretta lettura file > 1MB;
modificata entrata prog mode AVR
scrittura 93Sx6 protette; |
luglio 2012 | firmware v0.8.0: supporto bus One-Wire e UNIO;
software v0.8.0: aggiunti DS2430,DS2431,DS2433,DS28EC20,DS1820;
11010-20-40-80-160;
251005,252005,254005,258005,251605,25X10,25X20,25X40,25X80,
25X16,25X32,25X64;
16F1782-3-4-6-7,12C508-9;
corretti algoritmi 24x1024/5 e 251024; |
gennaio 2012 | software v0.7.10: aggiunti 12F617,12F1501,16F1503-7-8-9,16F720-21,16F72,16F707,
18F13K22,18F14K22,18F23K22,18F43K22,18F24K22,18F44K22,18F25K22,
18F45K22,18F26K22,18F46K22,18F8520,18F66J60,18F66J65,18F67J60,
18F86J60,18F86J65,18F87J60,18F96J60,18F96J65,18F97J60,
corretta lettura/scrittura file binari, varie correzioni,
supporto ICD in OPGUI |
giugno 2011 | software v0.7.9: aggiunti ATtiny11-12-24-26-261-44-48-461-4313-84-88-861,
ATmega48-88-164A-168-324A-328-644A-1284, 16LF1902-3-4-6-7,
varie modifiche minori e correzioni;
nuova interfaccia grafica GTK per Linux e Windows |
aprile 2011 | software v0.7.8: aggiornati algoritmi 16F87xA e 16F62xA,
16F1822 diventa 12F1822, aggiunti 30F1010, 30F2020, 30F2023, 16F1847, 12F1840
16F1516, 16F1517, 16F1518, 16F1519, 16F1526, 16F1527
maggiore modularità del codice, corretti alcuni bachi |
agosto 2010 | software v0.7.7: aggiunti 16F72x, altre modifiche minori;
circuiti v1.7.1: ridotto valore resistenza R173 nel modulo PIC16/18 LV |
luglio 2010 | firmware v0.7.6: istruzioni TX16 e RX16 con periodo variabile per comunicazioni ICD;
software v0.7.6: lettura byte a byte con 93xx6 per maggiore compatibilità;
prima versione debugger pdb (v0.1) |
giugno 2010 | software v0.7.5: corretto baco in scrittura config 18Fx,
aggiunta scrittura "goto ICD" per i 16Fx, correzioni minori; |
maggio 2010 | software v0.7.4: aggiunti PIC18FxJx, PIC18FxKx, PIC24H, dsPIC30-33, ATtiny2313, 241024;
corretti vari bachi;
circuiti v1.7: modifica sulla scheda per PIC24-30-33, PIC30 ora a 5V |
aprile 2010 | software v0.7.3: aggiunti PIC16F1xxx; corretti vari bachi; OP per win.;
circuiti v1.6: scheda per PIC16-18 a 3,3V |
marzo 2010 | software v0.7.2: aggiunte alcune memorie MicroWire; corretti vari bachi |
febbraio 2010 | software v0.7.1: aggiunti alcuni micro PIC18 e Atmel; corretti vari bachi |
gennaio 2010 | versione 0.7.0: aggiunti PIC24 e EEPROM SPI;
circuiti v1.5: scheda per PIC24-30-33 a 3,3V |
ottobre 2009 | software v0.6.2: risolti alcuni bachi |
settembre 2009 | versione 0.6.1: risolti alcuni bachi SPI, aggiunti alcuni Atmel e 93Cx6C |
giugno 2009 | versione 0.6: firmware USB GPL2, aggiunte memorie MicroWire 93Sx6 |
aprile 2009 | schema elettrico e pcb v1.4: modifica alla scheda Atmel |
marzo 2009 | software v0.5.2 e v0.5.3: aggiunti alcuni PIC e Atmel, corretti vari bachi |
gennaio 2009 | software v0.5.1: aggiunti alcuni PIC, corretti vari bachi |
novembre 2008 | versione 0.5: bus I2C e SPI, aggiunti alcuni micro Atmel |
agosto 2008 | versione 0.4: aggiunto supporto per EEPROM I2C |
luglio 2008 | documentazione e sito, pubblicata versione 0.3 |
2008 | primi prototipi e software |
2007 | esperimenti con i PIC USB e vari firmware; regolatore di tensione |
molto tempo fa | necessità di un programmatore USB affidabile e gratuito |
Link interessanti
Open Programmer su SourceForge
Breve guida al firmware HID
pdb, un semplice debugger ICD per PIC16
openprog_tools, un fork di op/opgui
MSYS2, toolchain ufficiale per windows
GTK3 runtime, librerie grafiche per windows
KiCad
Microchip (e Atmel)
Standard USB 2.0
HID page on USB.org
USB & PIC
Documentazione su hiddev
ICprog
Octave
gEDA project
licenze GNU/GPL
Piklab IDE for PIC microcontrollers
USBPicprog, un altro programmatore open source
Cygwin, un ambiente linux dentro windows
Contatti
Per informazioni o commenti:
Alberto Maccioni
Cosiglio anche di usare i
forum su sourceforge.
Ringraziamenti
Vorrei ringraziare tutti quelli che hanno contribuito alla crescita di questo progetto, in particolare:
Anselmo per le problematiche linux/SCM, Sandro per i PCB altamente professionali, Alessandro per la verifica di parecchi
dispositivi, Ken per la verifica di parecchi AVR, Luigi per la verifica di memorie OneWire,
Mihaly per la verifica di memorie Flash SPI.