Pagina 1 di 2

PIC16F1829 problema con numeri random

MessaggioInviato: 1 giu 2015, 12:24
da Nick01
Innanzitutto mi presento sono Nicola è un piacere entrare a far parte del forum. Ho un problema per quanto riguarda i numeri random con il PIC16F1829. A casa dispongo di un pickit3 con la demoboard Low Pin Count che desidererei utilizzare per realizzare un gioco con i led, ora posto lo schema

Il gioco che vorrei fare è un classico quello dei led che si accendono in maniera casuale e i pulsanti che servono per verificare se hai memorizzato correttamente la sequenza.
Per prima cosa vorrei che si accendesse un led alla volta in maniera casuale tra quelli qui sopra proposti, si dovrebbero accendere 3 led in totale. Ho già provato a scrivere il codice più volte ma ottenendo scarsi risulati, perché inizialmente si accendono due o tre led più o meno bene e poi c'è la sequenza dei tre led che a me occorre. Ecco io vorrei chiedervi se questo problema iniziale è dovuto al codice che ho scritto.
Ecco di seguito il codice:
Codice: Seleziona tutto
// PIC16F1829 Configuration Bit Settings

// 'C' source line config statements

#include <xc.h>

// CONFIG1
#pragma config FOSC = INTOSC   
#pragma config WDTE = OFF       
#pragma config PWRTE = OFF     
#pragma config MCLRE = OFF     
#pragma config CP = OFF         
#pragma config CPD = OFF       
#pragma config BOREN = OFF     
#pragma config CLKOUTEN = OFF   
#pragma config IESO = OFF       
#pragma config FCMEN = OFF     

// CONFIG2
#pragma config WRT = OFF       
#pragma config PLLEN = OFF     
#pragma config STVREN = OFF   
#pragma config BORV = LO       
#pragma config LVP = OFF       

#include <stdlib.h>
#include <stdio.h>
#define _XTAL_FREQ 16000000 //Definisco la frequenza di lavoro non quella del clock

int cont = 3;
int i; //Variabile per il numero casuale
int contLed = 0; int contPuls = 0; int controllo = 0; //Variabili contatori per i cicli
int led[] = {1,2,4}; //Vettore che imdica quale led deve lampeggiare

void delayMS(unsigned int count); //Funzione per il ritardo espressa in ms

void main(void) {

    TRISA = 0b11111111; //Imposto i pin come INPUT = 1 o OUTPUT = 0
    TRISB = 0b11111111;
    TRISC = 0b11111000;
    OSCCON = 0b01111010; //Clock interno impostato su 16MHZ
    ANSELA = 0b00000000; //Imposto i pin come digitali
    PORTC = 0b00000000;
    delayMS(500);
   
    while(1){ //Ciclo infinito dove si andrà a scrivere il programma
           
            while(contLed < cont){ //Ciclo che memorizza i led acccesi in sequenza
                i = rand() % 3;
                PORTC =  led[i];
                delayMS(300);
                PORTC = 0b00000000;
                delayMS(300);
                contLed = contLed + 1;
            }
    }
}

void delayMS(unsigned int count){
    while(count-- !=0){
        __delay_us(1000);
    }
}


(Ho provato a usare anche srand(time(NULL)) includendo la libreria time.h però anche in questo caso i risultati non erano nei migliori).
Questa è solo una parte del mio programma se desiderate lo copio tutto e se desiderate altre informazioni chiedete pure.
Grazie mille in anticipo

Re: PIC16F1829 problema con numeri random

MessaggioInviato: 1 giu 2015, 12:59
da TardoFreak
Generare numeri random non è cosa semplicissima, si incorre sempre nella stessa sequenza.
Puoi ovviare a questo problema utilizzando un'interrupt ciclica molto veloce che ti incrementa una variabile ed un evento esterno, come la pressione di un pulsante.
Quando rilevi la pressione del pulsante prendi il valore della variabile di cui sopra (che a questo punto sarà sicuramente casuale) e lo utilizzi per inzializza il generatore di numeri pseudo random con srand(variabile).

Re: PIC16F1829 problema con numeri random

MessaggioInviato: 1 giu 2015, 13:40
da Nick01
Ti ringrazio per la tempestiva risposta, ma che tu ci creda o no io non ho mai utilizzato un interrupt (abbiamo iniziato quest'anno a programmare PIC e io mi sto portando avanti con il lavoro facendo nuovi progettini :D ), potresti darmi qualche nozione o indicarmi qualche fonte su internet affidabile da cui imparare a usare questi benedetti interrupt? :D
Adesso sto leggendo un po' qua e là su internet, il bit PEIE del registro INTCON abilita gli interrupt per le periferiche, per periferiche si intende ad esempio il pulsante?
Volevo farti un'altra domanda la variabile in questione, aumenta di uno ad ogni pressione del tasto?

Re: PIC16F1829 problema con numeri random

MessaggioInviato: 1 giu 2015, 15:02
da WALTERmwp
Nick01 ha scritto:qualche fonte su internet affidabile da cui imparare a usare questi benedetti interrupt?

Ciao Foto UtenteNick01, ma provare a cercare su EY ?
"Chi" ti ha risposto al Post [2] ne ha ampiamente trattato nei suoi articoli, dai una sbirciatina al suo blog.

Saluti

Re: PIC16F1829 problema con numeri random

MessaggioInviato: 1 giu 2015, 15:06
da TardoFreak
OK, passiamo ad una soluzione alternativa senza usare interrupt.
Andiamo ad aggiungere un pezzo di programma prima del ciclo di funzionamento infinito.
In pratica scriviamo un ciclo che "pianta" il micro fino a quando non si preme un pulsante.
Butto giù di getto il codice
Codice: Seleziona tutto
unsigned char portcOld;
unsigned short int seme;

portcOld = PORTC & 0x07;
while (portCold == (PORTC & 0x07)
{
  seme++;
  portcOld = PORTC & 0x07;
}
srand(seme);

Il micro rimane inchiodato in questo ciclo fino a quando non viene premuto un tasto qualsiasi. Il valore di seme viene continuamente incrementato e poco importa se va in overflow, la cosa non ci interessa.
Ci interessa il fatto che all' uscita del ciclo avrà un valore casuale con cui inizializzzeremo il generatore di numeri pseudo-random.

Re: PIC16F1829 problema con numeri random

MessaggioInviato: 1 giu 2015, 15:22
da Nick01
WALTERmwp ha scritto:"Chi" ti ha risposto al Post [2] ne ha ampiamente trattato nei suoi articoli, dai una sbirciatina al suo blog.

Grazie mille andrò a leggerli il più presto possibile.

Foto UtenteTardoFreak ti ringazio per il codice entro stasera proverò il tutto poi vi farò sapere.
Grazie ancora

Re: PIC16F1829 problema con numeri random

MessaggioInviato: 1 giu 2015, 20:37
da Nick01
Il codice che mi hai dato funziona perfettamente, l'ho solo un po' riadattato al pin RA5:
Codice: Seleziona tutto
while (portaOld == (RA5 & 0x07)){
                if(RA5 == 0){
                    delayMS(30);
                    if(RA5 == 0){
                        break;
                    }
            }
                seme++;
                portaOld = RA5 & 0x07;
            }
            srand(seme);


Ora però sorge un altro problema: come vi ho detto dopo aver eseguito la sequenza casuale si dovrebbe passare alla memorizzazione della sequenza dei pulsanti premuti però questo non avviene in quanto il PIC salta questo ciclo,senza alcun motivo. Questo è il pezzo di codice:
Codice: Seleziona tutto
int cont = 3; int contPuls = 0;
while(contPuls < cont){ //Ciclo che memorizza i tasti da noi premuti in sequenza
                if(RA0 == 0){
                    delayMS(30); //Ritardo per evitare il rimbalzo
                    if(RA0 == 0){
                        memPuls[contPuls] = 1;
                        contPuls = contPuls + 1;
                    }
                }
                if(RA1 == 0){
                    delayMS(30); //Ritardo per evitare il rimbalzo
                    if(RA1 == 0){
                        memPuls[contPuls] = 2;
                        contPuls = contPuls + 1;
                    }
                }
                if(RA2 == 0){
                    delayMS(30); //Ritardo per evitare il rimbalzo
                    if(RA2 == 0){
                        memPuls[contPuls] = 3;
                        contPuls = contPuls + 1;
                    }
                }
            }


I pulsanti sono collegati come sopra nello schema, non riesco a spiegarmi il perché di tutto questo.

Re: PIC16F1829 problema con numeri random

MessaggioInviato: 1 giu 2015, 23:08
da WALTERmwp
Ho la sensazione che per quanto hai replicato qualcosa non ti sia chiaro; per quale motivo esegui il test di un pin in questo modo ?
Codice: Seleziona tutto
(portaOld == (RA5 & 0x07)
Per questo
Nick01 ha scritto:dopo aver eseguito la sequenza casuale si dovrebbe passare alla memorizzazione della sequenza dei pulsanti premuti però questo non avviene in quanto il PIC salta questo ciclo,senza alcun motivo.
come si fa a rispondere se non si conosce quanto precede il codice che hai riportato ?

Saluti

Re: PIC16F1829 problema con numeri random

MessaggioInviato: 2 giu 2015, 10:19
da Nick01
Foto UtenteWALTERmwp ho capito pienamento quello dettomi nel post[5] però hai ragione potevo semplificarlo:
Codice: Seleziona tutto
while (RA5 == 1){
                if(RA5 == 0){
                    delayMS(30);
                    if(RA5 == 0){
                        break;
                    }
            }
                seme++;
            }
            srand(seme);


E questo è il codice completo:
Codice: Seleziona tutto
#include <xc.h>
// CONFIG1
#pragma config FOSC = INTOSC   
#pragma config WDTE = OFF       
#pragma config PWRTE = OFF     
#pragma config MCLRE = OFF     
#pragma config CP = OFF         
#pragma config CPD = OFF       
#pragma config BOREN = OFF     
#pragma config CLKOUTEN = OFF   
#pragma config IESO = OFF       
#pragma config FCMEN = OFF     

// CONFIG2
#pragma config WRT = OFF       
#pragma config PLLEN = OFF     
#pragma config STVREN = OFF   
#pragma config BORV = LO       
#pragma config LVP = OFF       

#include <stdlib.h>
#include <stdio.h>
#define _XTAL_FREQ 16000000 //Definisco la frequenza di lavoro non quella del clock

int cont = 3;
int i; //Variabile per il numero casuale
int esito = 1; //Variabile per verificare la correttezza della sequenza
int contLed = 0; int contPuls = 0; int controllo = 0; //Variabili contatori per i cicli
int memLed[10]; int memPuls[10]; //Vettori che memorizzano quale led o pulsante è stato premuto
int led[] = {1,2,4}; //Vettore che imdica quale led deve lampeggiare

void delayMS(unsigned int count); //Funzione per il ritardo espressa in ms

void main(void) {

    TRISA = 0b11111111; //Imposto i pin come INPUT = 1 o OUTPUT = 0
    TRISB = 0b11111111;
    TRISC = 0b11111000;
    OSCCON = 0b01111010; //Clock interno impostato su 16MHZ
    ANSELA = 0b00000000; //Imposto i pin come digitali
    PORTC = 0b00000000;
    delayMS(500);
    unsigned short int seme;
   
   
    while(1){ //Ciclo infinito dove si andrà a scrivere il programma
        while(esito == 1){
           
            while (RA5 == 1){
                if(RA5 == 0){
                    delayMS(30);
                    if(RA5 == 0){
                        break;
                    }
            }
                seme++;
            }
            srand(seme);
           
            while(contLed < cont){ //Ciclo che memorizza i led acccesi in sequenza
                i = rand() % 3;
                PORTC =  led[i];
                delayMS(300);
                switch(i){
                    case 0: memLed[contLed] = 1;
                    break;
                    case 1: memLed[contLed] = 2;
                    break;
                    case 2: memLed[contLed] = 3;
                    break;
                }
                PORTC = 0b00000000;
                delayMS(300);
                contLed = contLed + 1;
            }
            delayMS(300);
            while(contPuls < cont){ //Ciclo che memorizza i tasti da noi premuti in sequenza
                if(RA0 == 0){
                    delayMS(30); //Ritardo per evitare il rimbalzo
                    if(RA0 == 0){
                        memPuls[contPuls] = 1;
                        contPuls = contPuls + 1;
                    }
                }
                if(RA1 == 0){
                    delayMS(30); //Ritardo per evitare il rimbalzo
                    if(RA1 == 0){
                        memPuls[contPuls] = 2;
                        contPuls = contPuls + 1;
                    }
                }
                if(RA2 == 0){
                    delayMS(30); //Ritardo per evitare il rimbalzo
                    if(RA2 == 0){
                        memPuls[contPuls] = 3;
                        contPuls = contPuls + 1;
                    }
                }
            }
           
            while(controllo < cont){
                if(memLed[controllo] == memPuls[controllo]){ //Controllo se i tasti premuti corrispondono ai led accesi
                    esito = 1;
                    controllo = controllo + 1;
                }
                else{
                    esito = 0;
                    break; //esco dal ciclo
                }
            }
           
            if(esito == 1){
                PORTC = 0b00000000;
                delayMS(300);
                PORTC = 0b00000111;
                delayMS(300);
                PORTC = 0b00000000;
                delayMS(300);
                cont += 1;
            }
            else{
                PORTC = 0b00000000;
                delayMS(300);
                PORTC = 0b00000001;
                delayMS(300);
                PORTC = 0b00000000;
                delayMS(300);
            }
            esito = 1;
        }
    }
}

void delayMS(unsigned int count){
    while(count-- !=0){
        __delay_us(1000);
    }
}

Re: PIC16F1829 problema con numeri random

MessaggioInviato: 2 giu 2015, 14:49
da WALTERmwp
Mi pare che nell'ultimo codice inserito nel Post manchi la ri-inizializzazione delle tre variabili di ciclo, a meno che mi sfugga alla vista; prima di
Codice: Seleziona tutto
while (RA5 == 1)
metti
Codice: Seleziona tutto
contLed=0; contPuls=0; controllo=0;
Però, dovesse essere questo il problema, significa che il programma verrebbe eseguito una volta sola, ma verrebbe eseuito.
Per il resto i loop(s) mi sembrano coerenti.
Non mi piace invece questo (l'uso del break)
Codice: Seleziona tutto
if(RA5 == 0)
{
    break;
}
però, è questione di gusti ...

Saluti