simon
Differenze
Queste sono le differenze tra la revisione selezionata e la versione attuale della pagina.
Entrambe le parti precedenti la revisioneRevisione precedenteProssima revisione | Revisione precedente | ||
simon [2021/01/11 21:31] – [Software] admin | simon [2023/10/27 18:02] (versione attuale) – [Software] admin | ||
---|---|---|---|
Linea 72: | Linea 72: | ||
Coi pulsanti - che a tutti gli effetti sono dei contatti normalmente aperti - si può generare un segnale alto o basso utilizzando i 3 Volt di alimentazione e una resistenza di [[wpi> | Coi pulsanti - che a tutti gli effetti sono dei contatti normalmente aperti - si può generare un segnale alto o basso utilizzando i 3 Volt di alimentazione e una resistenza di [[wpi> | ||
- | I LED si collegano ai pin dei pulsanti corrispondenti. Quando i pin, usati come uscite, saranno al livello basso permetteranno alla corrente di scorrere dall' | + | I LED si collegano ai pin dei pulsanti corrispondenti. Quando i pin, usati come uscite, saranno al livello basso permetteranno alla corrente di scorrere dall' |
`R = (V_(\C\C)-V_F)/ | `R = (V_(\C\C)-V_F)/ | ||
Linea 89: | Linea 89: | ||
* il circuito non è simulabile (non si simula un microcontrollore!) | * il circuito non è simulabile (non si simula un microcontrollore!) | ||
* il componente ATtiny13A non è disponibile in Multisim e va creato | * il componente ATtiny13A non è disponibile in Multisim e va creato | ||
- | * tutti i componenti neri non hanno un footprint e non vengono considerati | + | * tutti i componenti neri non hanno un footprint e non vengono considerati |
* il colore dei LED non è importante perché in fase di montaggio si possono montare in qualunque ordine (i resistori sono tutti uguali) | * il colore dei LED non è importante perché in fase di montaggio si possono montare in qualunque ordine (i resistori sono tutti uguali) | ||
Linea 97: | Linea 97: | ||
* __assegnare i footprint corretti__ agli altri componenti, se possibile (LED e buzzer non lo consentono e bisogna farlo in Ultiboard) | * __assegnare i footprint corretti__ agli altri componenti, se possibile (LED e buzzer non lo consentono e bisogna farlo in Ultiboard) | ||
- | **Prima di creare | + | Per risparmiare tempo è possibile utilizzare |
- | * resistori: | + | * in Mutisim cliccando col tasto destro e scegliendo |
- | * LED: '' | + | * in Ultiboard selezionando il componente e scegliendo |
- | * ATtiny13A: | + | |
- | * pulsanti: footprint custom | + | |
- | * portabatteria: | + | |
- | * buzzer: footprint custom | + | |
+ | In alternativa si procede come descritto nel paragrafo seguente. | ||
- | Fatte queste considerazioni | + | Dopo aver creato footprint (portabatteria, |
- | {{:simon_4b.png|}} | + | {{:: |
+ | ==== Creare un componente in Multisim ==== | ||
+ | **NB non è necessario se si importano i simboli del file Multisim disponibile tra le risorse** | ||
+ | |||
+ | **Prima di creare i componenti conviene [[simon# | ||
+ | * buzzer: footprint custom '' | ||
+ | * ATtiny13A: '' | ||
+ | * pulsanti: footprint custom '' | ||
+ | * portabatteria: | ||
- | ==== Creare un componente in Multisim ==== | ||
Si usa una procedura guidata: | Si usa una procedura guidata: | ||
Linea 137: | Linea 141: | ||
Indicazioni per la creazione del pulsante TACT-65R-F: | Indicazioni per la creazione del pulsante TACT-65R-F: | ||
* step 1: TACT-65R-F, NINIGI, Tactile Switch SPST-NO, layout only | * step 1: TACT-65R-F, NINIGI, Tactile Switch SPST-NO, layout only | ||
- | * step 2: footprint custom TACT-SPST da creare in Ultiboard copiandolo da SKHH1_1 | + | * step 2: footprint custom TACT-SPST da creare in Ultiboard copiandolo da SKHH1 (in //Through Hole Technoly Parts|Buttons and Switches|Tact// |
* step 3: copiare da DPST-2NO-DB (//Electro mechanical|Supplementary switches//) e modificare aggiustando il nome dei pin del simbolo | * step 3: copiare da DPST-2NO-DB (//Electro mechanical|Supplementary switches//) e modificare aggiustando il nome dei pin del simbolo | ||
* step 4: nominare i pin come indicato nel datasheet | * step 4: nominare i pin come indicato nel datasheet | ||
Linea 143: | Linea 147: | ||
* step 6: creare la famiglia //SWITCH// nel gruppo //Basic// del database User e cliccare su //Finish// | * step 6: creare la famiglia //SWITCH// nel gruppo //Basic// del database User e cliccare su //Finish// | ||
- | Indicazioni per la creazione del portabatteria DS1092-05: | + | Indicazioni per la creazione del portabatteria DS1092-04: |
- | * step 1: <del>DS1092-05</ | + | * step 1: DS1092-04, Connfly, CR2032 battery holder, layout only |
- | * step 2: footprint custom | + | * step 2: footprint custom DS1092-04 da creare in Ultiboard secondo usando le informazioni contenute nel datasheet |
* step 3: copiare da 1028 (in // | * step 3: copiare da 1028 (in // | ||
* step 4: accettare la piedinatura | * step 4: accettare la piedinatura | ||
Linea 152: | Linea 156: | ||
===== Layout del PCB ===== | ===== Layout del PCB ===== | ||
+ | |||
+ | In questa fase di procede alla definizione delle dimensioni della scheda, poi al layout (posizionamento) dei componenti e infine allo sbroglio, cioè al disegno delle piste in rame che collegano i componenti **che non devono mai toccarsi o incrociarsi**. | ||
Requisiti per la realizzazione nella sala acidi della scuola: | Requisiti per la realizzazione nella sala acidi della scuola: | ||
* single layer | * single layer | ||
* piste da 1 mm | * piste da 1 mm | ||
- | * testo specchiato col nome dello studente | + | |
+ | | ||
* massimo 2 piste sotto l' | * massimo 2 piste sotto l' | ||
Altri requisiti: | Altri requisiti: | ||
* dimensioni massime 6 x 5 cm | * dimensioni massime 6 x 5 cm | ||
- | * pulsanti facilmente raggiungibili | + | * pulsanti facilmente raggiungibili |
* minimizzare ingombri | * minimizzare ingombri | ||
Indicazioni varie: | Indicazioni varie: | ||
* imparare a usare i filtri di selezione! | * imparare a usare i filtri di selezione! | ||
+ | * imparare a misurare le dimensioni usando le indicazioni delle coordinate in basso a destra; un click del mouse imposta il punto di partenza della misura poi dx, dy e L indicano lo spostamento orizzontale, | ||
* ridimensionare il board outline prima di piazzare i componenti (selezionare il layer //Board outline// e attivare il filtro //Enable selecting other objects// per cambiare le dimensioni del rettangolo giallo che delimita il PCB) | * ridimensionare il board outline prima di piazzare i componenti (selezionare il layer //Board outline// e attivare il filtro //Enable selecting other objects// per cambiare le dimensioni del rettangolo giallo che delimita il PCB) | ||
* posizionare e ruotare i componenti per facilitare lo sbroglio | * posizionare e ruotare i componenti per facilitare lo sbroglio | ||
- | * disabilitare l' | + | * disabilitare l' |
- | * impostare l' | + | * impostare l' |
- | * dove è possibile usare piazzole circolari con foro da 0,6mm e diametro 2,6mm | + | * dove è possibile usare piazzole circolari con foro da 0,6 mm e diametro 2,6 mm |
- | * per i componenti con i pin troppo vicini tra loro usare [[simon# | + | * per i componenti con i pin troppo vicini tra loro usare piazzole ovali (o [[simon# |
* imparare a creare footprint custom | * imparare a creare footprint custom | ||
Cominciamo così: | Cominciamo così: | ||
* la prima volta che si passa da Multisim a Ultiboard si usa // | * la prima volta che si passa da Multisim a Ultiboard si usa // | ||
- | * se dopo aver creato | + | * se dopo aver iniziato |
- | * la prima cosa da fare è guardare | + | * la prima cosa da fare è osservare se il footprint dei vari componenti |
+ | |||
+ | Andranno cambiati i footprint di: | ||
+ | * resistori scegliendo '' | ||
+ | * LED: '' | ||
+ | |||
+ | Prima di procedere allo sbroglio è bene anche aggiustare se necessario le dimensioni delle piazzole: | ||
+ | * dove possibile foro da 0,6mm e diametro 2,6mm | ||
+ | * per microcontrollore e LED piazzole ovali, scegliendo //Rounded Rectangle// con foro da 0,6mm e Pad diameter 3mm, Length 1,8mm e Corner radius 0,9mm | ||
Dopo aver ridimensionato il PCB si dovrebbe ottenere qualcosa di simile: | Dopo aver ridimensionato il PCB si dovrebbe ottenere qualcosa di simile: | ||
Linea 185: | Linea 201: | ||
Da qui si procede con lo sbroglio, piazzando i componenti e tracciando le piste. Qualche indicazione: | Da qui si procede con lo sbroglio, piazzando i componenti e tracciando le piste. Qualche indicazione: | ||
* bisogna fare più tentativi, spostando i componenti e ridisegnando le piste, per trovare la soluzione migliore | * bisogna fare più tentativi, spostando i componenti e ridisegnando le piste, per trovare la soluzione migliore | ||
- | * seguire le // | + | * seguire le // |
* fare attenzione a non sovrapporre piste/ | * fare attenzione a non sovrapporre piste/ | ||
* verificare che la // | * verificare che la // | ||
- | * verificare che il PCB abbia l' | + | * verificare che il PCB abbia l' |
* a sbroglio completato verificare che il progetto non contenga errori osservando il risultato nella scheda //Results// della // | * a sbroglio completato verificare che il progetto non contenga errori osservando il risultato nella scheda //Results// della // | ||
* // | * // | ||
Linea 194: | Linea 210: | ||
Un possibile sbroglio è mostrato in figura: | Un possibile sbroglio è mostrato in figura: | ||
+ | |||
+ | |||
+ | |||
+ | |||
{{: | {{: | ||
- | Il render 3D ha questo aspetto: | + | |
+ | Il render | ||
+ | |||
+ | |||
+ | |||
{{:: | {{:: | ||
+ | |||
+ | |||
==== Creare un footprint ==== | ==== Creare un footprint ==== | ||
- | Ultiboard organizza i footprint in più database; quello predefinito si chiama //Ultiboard Master// e contiene i footprint di migliaia di componenti. Quando un progetto include un componente il cui footprint | + | **NB non è necessario se si importano i footprint del file Ultiboard disponibile tra le risorse** |
+ | |||
+ | Ultiboard organizza i footprint in più database; quello predefinito si chiama //Ultiboard Master// e contiene i footprint di migliaia di componenti. Quando un progetto include un componente il cui footprint non è disponibile in questo database bisogna crearne uno custom e salvarlo nel database //User//. Si può: | ||
* creare il footprint da zero e salvarlo nel database //User// | * creare il footprint da zero e salvarlo nel database //User// | ||
* copiare un footprint dal database master per poi modificarlo e salvarlo nel database //User// | * copiare un footprint dal database master per poi modificarlo e salvarlo nel database //User// | ||
- | * importare un footprint da un file Ultiboard dal //Database Manager// | + | * importare un footprint da un file Ultiboard dal //Database Manager// |
Il footprint di buzzer e portabatteria va creato da zero, quello dei pulsanti si può fare modificandone uno di Ultiboard. | Il footprint di buzzer e portabatteria va creato da zero, quello dei pulsanti si può fare modificandone uno di Ultiboard. | ||
Linea 213: | Linea 242: | ||
* nella vista ad albero a sinistra selezionare //User database// (in questa fase, volendo si può creare un gruppo/ | * nella vista ad albero a sinistra selezionare //User database// (in questa fase, volendo si può creare un gruppo/ | ||
* cliccare l' | * cliccare l' | ||
- | * l' | + | * l' |
* piazzare i pin con // | * piazzare i pin con // | ||
- | * utilizzando il layer // | + | * utilizzando il layer // |
* dopo aver **controllato attentamente le dimensioni del layout((le misure si possono fare cliccando in un punto e osservando in basso a destra il valore delle coordinate e delle distanze dX dY e L)), la distanza tra i piedini e il posizionamento dei piedini nel layout del componente** salvare il footprint nel database User (eventualmente in un gruppo adatto) dandogli un nome significativo | * dopo aver **controllato attentamente le dimensioni del layout((le misure si possono fare cliccando in un punto e osservando in basso a destra il valore delle coordinate e delle distanze dX dY e L)), la distanza tra i piedini e il posizionamento dei piedini nel layout del componente** salvare il footprint nel database User (eventualmente in un gruppo adatto) dandogli un nome significativo | ||
==== Creare una piazzola custom ==== | ==== Creare una piazzola custom ==== | ||
- | I LED e l' | + | **NB non è necessario da Multism 14.2 o superiore** |
+ | |||
+ | I LED e l' | ||
Creare la piazzola custom: | Creare la piazzola custom: | ||
Linea 245: | Linea 276: | ||
===== Software ===== | ===== Software ===== | ||
- | Il programma che caricheremo nel microcontrollore non usa nessuna delle funzioni di Arduino ma opera direttamente sui registri dell' | + | Il programma(({{ : |
Il programma non è spiegato nel dettaglio ma dai commenti si capisce come funziona. | Il programma non è spiegato nel dettaglio ma dai commenti si capisce come funziona. | ||
Prerequisiti: | Prerequisiti: | ||
- | * sapere come funzionano gli [[wpi> | + | * sapere come funzionano gli [[wpi> |
* essere in grado di trovare le informazioni nel datasheet di un microcontrollore, | * essere in grado di trovare le informazioni nel datasheet di un microcontrollore, | ||
* saper programmare in C | * saper programmare in C | ||
Linea 300: | Linea 331: | ||
SCOPO DEL PROGRAMMA | SCOPO DEL PROGRAMMA | ||
Il codice implementa il classico gioco Simon con 4 LED, 4 pulsanti | Il codice implementa il classico gioco Simon con 4 LED, 4 pulsanti | ||
- | e una sequenza di luci e suoni di memorizzar | + | e una sequenza di luci e suoni da memorizzare |
- | | + | |
- | il gioco e si allunga ogni volta che il giocatore la riproduce | + | il gioco e si allunga ogni volta che il giocatore la riproduce. |
- | | + | |
- | | + | |
- | score tenere premuto il pulsante del LED rosso durante lo start) | + | score tenere premuto il pulsante del LED rosso durante lo start). |
- | | + | |
- | avvio per il random generator | + | avvio per il random generator. |
- | | + | |
PREREQUISITI | PREREQUISITI | ||
- | generalità sui microcontrollori e programmazione in C, saper leggere | + | |
- | un datasheet lungo e complesso, bitwise operation e bit masking per | + | |
- | | + | - bitwise operation e bit masking per la gestione dei registri |
CONFIGURAZIONE | CONFIGURAZIONE | ||
- | Il MCU va configurato per andare a 1.2MHz | + | Il MCU va configurato per andare a 1.2MHz o l' |
- | scegliere una delle due frequenze e il valore del prescaler) | + | |
- | | + | |
REGISTRI PIU' IMPORTANTI UTILIZZATI | REGISTRI PIU' IMPORTANTI UTILIZZATI | ||
I numeri di pagina nei commenti fanno riferimento al datasheet | I numeri di pagina nei commenti fanno riferimento al datasheet | ||
dell' | dell' | ||
- | c'è il link alle pagine che descrivono i registri e sono indicati | + | c'è il link alle pagine che descrivono i registri e i loro valori di |
- | | + | default: |
- | DDRB = 0b00000000 -> tutti ingressi | + | DDRB = 0b00000000 -> tutti ingressi |
- | PORTB = | + | PORTB |
ADCSRA = 0b00000000 -> ADC spento | ADCSRA = 0b00000000 -> ADC spento | ||
- | ADMUX = | + | ADMUX |
- | INGRESSI E USCITE | + | |
- | DDRB imposta come uscite i bit a 1 (pagina 50). I pin sono sempre | + | DDRB imposta come uscite i pin che hanno il bit corrispondente |
- | | + | |
- | Il pin 5 (PB5) viene usato pulsante | + | |
- | | + | Il pin 1 (PB5) è usato sia per il pulsante start (è un RESET attivo |
- | il seed del random generator | + | |
+ | il seed del random generator. | ||
Il pin 6 (PB1/OC0B) è usato per pilotare il buzzer con un' | Il pin 6 (PB1/OC0B) è usato per pilotare il buzzer con un' | ||
- | quadra generata col timer/ | + | quadra generata col timer/ |
Per la gestione del timer/ | Per la gestione del timer/ | ||
Linea 345: | Linea 376: | ||
frequenza, e quello in corrispondenza del quale c'è la commutazione | frequenza, e quello in corrispondenza del quale c'è la commutazione | ||
tra livello alto e basso. Il waveform generator usa il risultato | tra livello alto e basso. Il waveform generator usa il risultato | ||
- | della comparazione per produrre un segnale PWM nel pin OC0B del buzzer | + | della comparazione per produrre un segnale PWM nel pin OC0B (buzzer). |
- | Il timer/clock si ferma se non si seleziona una sorgente di clock; | + | Il timer/counter |
- | | + | |
- normal: conta in su fino a 0xFF poi genera un interrupt e ricomincia | - normal: conta in su fino a 0xFF poi genera un interrupt e ricomincia | ||
- CTC: conta fino a OCR0A | - CTC: conta fino a OCR0A | ||
- fast PWM: va basso sul match con OCR0A e alto su 0xFF (fig. 11-6) | - fast PWM: va basso sul match con OCR0A e alto su 0xFF (fig. 11-6) | ||
- phase correct PWM: conta in su e in giù | - phase correct PWM: conta in su e in giù | ||
- | Nel programma si usa la modalità phase correct PWM per il buzzer | + | Nel programma si usa la modalità phase correct PWM per il buzzer. |
*/ | */ | ||
Linea 361: | Linea 392: | ||
// sleep mode | // sleep mode | ||
// Al termine di ogni partita, se scade il watchdog timer il MCU va in | // Al termine di ogni partita, se scade il watchdog timer il MCU va in | ||
- | // POWER-DOWN per ridurre il consumo; si risveglia col un reset | + | // POWER-DOWN per ridurre il consumo; si risveglia col un reset. |
#include < | #include < | ||
// delay | // delay | ||
- | // funzione simile a delay() di Arduino (cicli di CPU buttati). Va va | + | // funzione simile a delay() di Arduino (cicli di CPU buttati). Va |
// bene per piccole temporizzazioni, | // bene per piccole temporizzazioni, | ||
// Il codice usa _delay_loop_2(t) dove t è un int a 16 bit; il ritardo | // Il codice usa _delay_loop_2(t) dove t è un int a 16 bit; il ritardo | ||
Linea 391: | Linea 422: | ||
// array con quattro valori usati dal waveform generator per produrre | // array con quattro valori usati dal waveform generator per produrre | ||
- | // le note: re# sol# do re# (2.5, 3.3, 4.2 e 5 kHz) | + | // le note: re fa# la re |
// vedere la funzione play() per interpretare i valori | // vedere la funzione play() per interpretare i valori | ||
const uint8_t tones[4] = { | const uint8_t tones[4] = { | ||
Linea 402: | Linea 433: | ||
// variabili per pseudo-random generator | // variabili per pseudo-random generator | ||
- | uint16_t seed; // generato con l'ADC su un pin scollegato (e mischiato) | + | uint16_t seed; // generato con l'ADC su un pin scollegato (poi mischiato) |
uint16_t ctx; // valori successivi generati a partire dal seed | uint16_t ctx; // valori successivi generati a partire dal seed | ||
// variabili volatile modificate dalla ISR del watchdog | // variabili volatile modificate dalla ISR del watchdog | ||
+ | // vedi http:// | ||
+ | // le motivazioni circa il qualificatore " | ||
volatile uint8_t nrot = 8; // quante volte si mischia il seed nella ISR | volatile uint8_t nrot = 8; // quante volte si mischia il seed nella ISR | ||
- | // usando il valore del timer | ||
volatile uint16_t time; // conteggio incrementato dall' | volatile uint16_t time; // conteggio incrementato dall' | ||
// usato per il debouncing dei pulsanti e per | // usato per il debouncing dei pulsanti e per | ||
Linea 442: | Linea 474: | ||
// imposta come uscite il buzzer e uno dei pin collegati ai LED | // imposta come uscite il buzzer e uno dei pin collegati ai LED | ||
- | // con i bit di PORTB a 0 (livello basso) il LED si accende | + | // con i bit di PORTB a 0 (livello basso) il LED si accende |
- | // buzzer viene generato il segnale PWM | + | |
DDRB = buttons[i]; | DDRB = buttons[i]; | ||
- | // a pagina 67 un diagramma temporale | + | // generazione |
+ | // modo PWM phase-correct | ||
+ | // - OCR0A e OCR0B impostano la frequenza della nota e il duty-cicle | ||
+ | // - bit di TTCR0B impostano il modo PWM e il prescaler | ||
+ | // la frequenza vale (pag. 68): f=(1.2M/ | ||
+ | // con i valori in tones (239, 179, 143, 119) -> 314 419 524 e 630 Hz | ||
+ | // che per qualche strana ragione che andrebbe investigata diventano | ||
+ | // re, fa#, la, re (294 370 440 587 Hz) | ||
+ | | ||
// assegno a OCR0A il valore massimo del conteggio del timer/ | // assegno a OCR0A il valore massimo del conteggio del timer/ | ||
- | // in modo da modificare la frequenza | + | // per modificare la frequenza (nota) |
- | // da pag. 68 si capisce che la frequenza minima si otterrebbe senza | + | |
- | // usare OCR0A (quindi contando sempre fino a 0xFF - 255 | + | |
- | // f = 1.2M/ | + | |
- | // con i valori in tones si ottiene ad es. f=1.2M/ | + | |
- | // gli altri valori sono 3.3, 4.2 e 5 kHz (re# sol# do re#) | + | |
OCR0A = tones[i]; | OCR0A = tones[i]; | ||
- | // e a OCR0B la sua metà | + | // assegno |
OCR0B = tones[i] >> 1; //shiftR di 1: 01110111 (239 diviso 2: 119) | OCR0B = tones[i] >> 1; //shiftR di 1: 01110111 (239 diviso 2: 119) | ||
- | // TCCR0A/B sono impostati | + | // TCCR0A |
- | // che il waveform generator funzioni in modalità PWM phase correct | + | // TTCR0B in modo che il waveform generator funzioni in modalità PWM |
- | // WGM02 imposta il conteggio fino a OCR0A (pag. 73) | + | // phase correct e conteggio fino a ORC0A con prescaler 8 |
- | // CS01 imposta il prescaler | + | |
TCCR0B = (1 << WGM02) | (1 << CS01); | TCCR0B = (1 << WGM02) | (1 << CS01); | ||
+ | // TTCR0A = 00100001 e TTCR0B = 00001010 quindi: | ||
+ | // WGM0[2:0] = 101 -> modo phase correct fino a OCR0A | ||
+ | // CS0[2:1] = 010 -> prescaler 8 | ||
// suona la nota e tiene il LED acceso per 150ms | // suona la nota e tiene il LED acceso per 150ms | ||
_delay_loop_2(t); | _delay_loop_2(t); | ||
- | // spegne il timer/ | + | // spegne il timer/ |
TCCR0B = 0b00000000; | TCCR0B = 0b00000000; | ||
Linea 483: | Linea 519: | ||
// se si batte l'high score salva il livello raggiunto su eeprom | // se si batte l'high score salva il livello raggiunto su eeprom | ||
if (lvl > maxLvl) { | if (lvl > maxLvl) { | ||
- | eeprom_write_byte((uint8_t*) 0, ~lvl); // write best score | + | eeprom_write_byte((uint8_t*) 0, ~lvl); // high score complementato |
// | // | ||
for (uint8_t i = 0; i < 3; i++) { | for (uint8_t i = 0; i < 3; i++) { | ||
Linea 501: | Linea 537: | ||
uint8_t simple_random4() { | uint8_t simple_random4() { | ||
// LFSR linear-feedback shift register (Galois) | // LFSR linear-feedback shift register (Galois) | ||
- | // per una spiegazione | + | // per una spiegazione |
- | // o la pagina wikipedia (e l'AN della Maxim linkata): | + | // o la pagina wikipedia (e l'Application Note della Maxim linkata): |
// it.wikipedia.org/ | // it.wikipedia.org/ | ||
- | // modifica | + | // Modifica |
// uno dei quattro LED | // uno dei quattro LED | ||
// la sequenza pseudo-casuale di valori di ctx si ripete sempre | // la sequenza pseudo-casuale di valori di ctx si ripete sempre | ||
// allo stesso modo se non cambia il seed; riportando ctx al valore | // allo stesso modo se non cambia il seed; riportando ctx al valore | ||
// del seed si può ripercorrere la sequenza e confrontarla con la | // del seed si può ripercorrere la sequenza e confrontarla con la | ||
- | // pressione dei pulsanti per capire se il giocatore ha sbagliato | + | // pressione dei pulsanti per capire se il giocatore ha sbagliato |
// servono due bit per un nuovo indice da 0 a 3 (00 -> 11) | // servono due bit per un nuovo indice da 0 a 3 (00 -> 11) | ||
Linea 539: | Linea 575: | ||
nrot--; | nrot--; | ||
// mischia il seed facendo uno shift a sinistra e XOR con il valore | // mischia il seed facendo uno shift a sinistra e XOR con il valore | ||
- | // del timer/ | + | // del timer/ |
// a 8bit senza prescaler, quindi a 1.2MHz | // a 8bit senza prescaler, quindi a 1.2MHz | ||
seed = (seed << 1) ^ TCNT0; | seed = (seed << 1) ^ TCNT0; | ||
Linea 555: | Linea 591: | ||
// GENERAZIONE DEL SEED | // GENERAZIONE DEL SEED | ||
- | | + | |
// Il pin PB5/ADC0 (start/ | // Il pin PB5/ADC0 (start/ | ||
- | // attivando l'ADC sul pin scollegato per ottenere un valore casuale | + | // attivando l'ADC sul pin scollegato per ottenere un valore casuale. |
- | // il valore viene poi mischiato per otto volte nella ISR richiamata | + | // Il valore viene poi mischiato per otto volte nella ISR richiamata |
// allo scadere del watchdog timer | // allo scadere del watchdog timer | ||
- | | + | |
// ADC | // ADC | ||
- | | + | |
ADCSRA |= (1 << ADEN); // abilita l'ADC (pagina 82 e 92) | ADCSRA |= (1 << ADEN); // abilita l'ADC (pagina 82 e 92) | ||
ADCSRA |= (1 << ADSC); // parte la conversione sul pin ADC0 scollegato | ADCSRA |= (1 << ADSC); // parte la conversione sul pin ADC0 scollegato | ||
Linea 573: | Linea 609: | ||
seed = ADCL; | seed = ADCL; | ||
ADCSRA = 0b00000000; // spegne l'ADC | ADCSRA = 0b00000000; // spegne l'ADC | ||
- | | + | |
// WATCHDOG TIMER | // WATCHDOG TIMER | ||
- | | + | |
// abilita l' | // abilita l' | ||
// il WDT usa un oscillatore separato che va a 128kHz (il timer invece | // il WDT usa un oscillatore separato che va a 128kHz (il timer invece | ||
Linea 583: | Linea 619: | ||
WDTCR = (1 << WDTIE); // parte il watchdog timer con prescaler da 16ms | WDTCR = (1 << WDTIE); // parte il watchdog timer con prescaler da 16ms | ||
sei(); // global interrupt enable (mette a 1 il bit I nello SREG) | sei(); // global interrupt enable (mette a 1 il bit I nello SREG) | ||
- | | + | |
- | // TIMER/ | + | // TIMER/ |
- | + | ||
// imposta il timer/ | // imposta il timer/ | ||
// prescaler (CS00 a uno): conta fino a 0xFF, segnala con TOV0 e | // prescaler (CS00 a uno): conta fino a 0xFF, segnala con TOV0 e | ||
Linea 592: | Linea 628: | ||
// clock (pag. 60) | // clock (pag. 60) | ||
TCCR0B = (1 << CS00); | TCCR0B = (1 << CS00); | ||
+ | // TTCR0A = 00000000 e TTCR0B = 00000001 quindi: | ||
+ | // - WGM0[2:0] = 000 -> normal mode (pag 73) | ||
+ | // - CS0[2:0] = 001 -> no prescaling (clock a 1,2MHz) | ||
// il watchdog timer scade otto volte e la ISR mischia il seed | // il watchdog timer scade otto volte e la ISR mischia il seed | ||
while (nrot); | while (nrot); | ||
- | // IMPOSTAZIONE | + | // TIMER/ |
// la modalità di funzionamento del timer cambia da normal mode a PWM | // la modalità di funzionamento del timer cambia da normal mode a PWM | ||
// phase correct (WGM0[2: | // phase correct (WGM0[2: | ||
- | // a 0xFF | + | // a 0xFF (tabella a pagina 73) |
// nella funzione play() invece, per cambiare la frequenza e produrre | // nella funzione play() invece, per cambiare la frequenza e produrre | ||
// note diverse, conterà fino al valore contenuto nel registro OCR0A | // note diverse, conterà fino al valore contenuto nel registro OCR0A | ||
- | // Si imposta il compare output mode del waveform generator | + | // Si imposta il compare output mode del waveform generator |
- | // che il pin del buzzer PB1/ | + | // (COM0B[1: |
- | // match col valore del registro OCR0B mentre conta in su e alto | + | // sul match col valore del registro OCR0B mentre |
- | // mentre conta in giù (OCR0B è impostato nella funzione play() come | + | // alto mentre |
- | // OCR0A / 2) | + | // quadra con la frequenza desiderata |
- | // in questo modo si genera un onda quadra con la frequenza desiderata | + | |
// NB il segnale PWM è presente solo se il pin è impostato come uscita | // NB il segnale PWM è presente solo se il pin è impostato come uscita | ||
- | // (pag 68) quindi il buzzer non suona finche non si chiama play() | + | // (pag 68) e se è impostata una sorgente per il clock (pag 60) quindi |
+ | // il buzzer non suona finche non si chiama play() | ||
TCCR0A = (1 << COM0B1) | (0 << COM0B0) | (0 << WGM01) | TCCR0A = (1 << COM0B1) | (0 << COM0B0) | (0 << WGM01) | ||
+ | // TTCR0A = 00100001 e TTCR0B = 00000001 quindi: | ||
+ | // - WGM0[2:0] = 001 -> phase correct mode (pag 73) | ||
+ | // - COM0B[1:0] = 10 -> reset up-counting, | ||
// LETTURA DELL' | // LETTURA DELL' | ||
- | | + | |
- | | + | // maxLvl viene complementato (con l' |
// o letto perché il valore di default su EEPROM è 0xFF (255 e non 0) | // o letto perché il valore di default su EEPROM è 0xFF (255 e non 0) | ||
// e con la EEPROM " | // e con la EEPROM " | ||
Linea 622: | Linea 664: | ||
// EVENTUALE RESET DELL' | // EVENTUALE RESET DELL' | ||
- | | + | |
// legge lo stato dei pin della port B e lo confronta con la maschera | // legge lo stato dei pin della port B e lo confronta con la maschera | ||
+ | // (dove 0 significa premuto) | ||
switch (PINB & 0b00011101) { | switch (PINB & 0b00011101) { | ||
// NB lo switch non è necessario; nel codice originale permetteva di | // NB lo switch non è necessario; nel codice originale permetteva di | ||
Linea 629: | Linea 672: | ||
// per ridurre le dimensioni dell' | // per ridurre le dimensioni dell' | ||
// sono state eliminate | // sono state eliminate | ||
- | // AND tra gli ingressi e la maschera sopra dove 0 significa premuto | ||
// PB1 e PB5 non contano: uno è il buzzer e l' | // PB1 e PB5 non contano: uno è il buzzer e l' | ||
// basso (che a questo punto del programma sarà già alto); i pin dei | // basso (che a questo punto del programma sarà già alto); i pin dei | ||
Linea 642: | Linea 684: | ||
while (1) { | while (1) { | ||
// MOSTRA LA SEQUENZA | // MOSTRA LA SEQUENZA | ||
- | | + | |
// reimposta ctx al valore del seed; la sequenza di valori di ctx | // reimposta ctx al valore del seed; la sequenza di valori di ctx | ||
// sarà sempre la stessa sequenza finché non si resetta | // sarà sempre la stessa sequenza finché non si resetta | ||
Linea 694: | Linea 736: | ||
if (i != correct) { | if (i != correct) { | ||
// accendi il LED giusto tante volte pari al livello raggiunto | // accendi il LED giusto tante volte pari al livello raggiunto | ||
- | for (uint8_t j = 0; j < lvl; j++) { | + | for (uint8_t j = 0; j <= lvl; j++) { |
_delay_loop_2(65536); | _delay_loop_2(65536); | ||
play(correct, | play(correct, | ||
Linea 739: | Linea 781: | ||
===== Programmazione del microcontrollore ===== | ===== Programmazione del microcontrollore ===== | ||
- | Per programmare il micro ATtiny13A useremo una scheda Arduino Uno come programmatore come descritto in [[https:// | + | Per programmare il micro ATtiny13A useremo una scheda Arduino Uno((funziona anche con una Arduino Duemilanove ma bisogna collegare un condensatore da 10uF tra reset e ground altrimenti l' |
La soluzione più semplice è quella di usare una breadboard e sei cavi rigidi collegati come nella figura seguente((LED e resistori non servono ma permettono di testare velocemente se la programmazione funziona caricando sul micro uno sketch che fa lampeggiare il led)): | La soluzione più semplice è quella di usare una breadboard e sei cavi rigidi collegati come nella figura seguente((LED e resistori non servono ma permettono di testare velocemente se la programmazione funziona caricando sul micro uno sketch che fa lampeggiare il led)): | ||
Linea 774: | Linea 816: | ||
* spazzolare la scheda per togliere il photoresist e facilitare la saldatura | * spazzolare la scheda per togliere il photoresist e facilitare la saldatura | ||
- | * forare | + | * forare |
* come saldare (vedi immagine) e la pagina sull' | * come saldare (vedi immagine) e la pagina sull' | ||
* montare i LED rispettando la polarità | * montare i LED rispettando la polarità | ||
Linea 793: | Linea 835: | ||
* {{ : | * {{ : | ||
* [[https:// | * [[https:// | ||
- | * <del>{{ :: | + | * {{ ::ds1092-04-b6p.pdf |datasheet portabatteria}} |
* [[https:// | * [[https:// | ||
+ | * [[https:// | ||
* Tutorial National Instruments | * Tutorial National Instruments | ||
* [[http:// | * [[http:// | ||
Linea 800: | Linea 843: | ||
* altro | * altro | ||
* [[https:// | * [[https:// | ||
+ | * [[https:// | ||
* [[https:// | * [[https:// | ||
* [[http:// | * [[http:// | ||
+ | * [[https:// | ||
* {{ : | * {{ : | ||
- | * [[https:// | ||
* {{ ::simon.zip |}} | * {{ ::simon.zip |}} | ||
* [[https:// | * [[https:// | ||
* {{ : | * {{ : | ||
+ | * {{ :: | ||
+ | |||
simon.txt · Ultima modifica: 2023/10/27 18:02 da admin