Cos'è ElectroYou | Login Iscriviti

ElectroYou - la comunità dei professionisti del mondo elettrico

PIC16F1829 problema con numeri random

Raccolta di codici sorgenti

Moderatore: Foto UtentePaolino

1
voti

[1] PIC16F1829 problema con numeri random

Messaggioda Foto UtenteNick01 » 1 giu 2015, 12:24

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
Avatar utente
Foto UtenteNick01
15 4
 
Messaggi: 31
Iscritto il: 29 mag 2015, 16:13

1
voti

[2] Re: PIC16F1829 problema con numeri random

Messaggioda Foto UtenteTardoFreak » 1 giu 2015, 12:59

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).
"La follia sta nel fare sempre la stessa cosa aspettandosi risultati diversi".
"Parla soltanto quando sei sicuro che quello che dirai è più bello del silenzio".
Rispondere è cortesia, ma lasciare l'ultima parola ai cretini è arte.
Avatar utente
Foto UtenteTardoFreak
73,8k 8 12 13
-EY Legend-
-EY Legend-
 
Messaggi: 15754
Iscritto il: 16 dic 2009, 11:10
Località: Torino - 3° pianeta del Sistema Solare

0
voti

[3] Re: PIC16F1829 problema con numeri random

Messaggioda Foto UtenteNick01 » 1 giu 2015, 13:40

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?
Avatar utente
Foto UtenteNick01
15 4
 
Messaggi: 31
Iscritto il: 29 mag 2015, 16:13

0
voti

[4] Re: PIC16F1829 problema con numeri random

Messaggioda Foto UtenteWALTERmwp » 1 giu 2015, 15:02

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
W - U.H.F.
Avatar utente
Foto UtenteWALTERmwp
29,5k 4 8 13
G.Master EY
G.Master EY
 
Messaggi: 8742
Iscritto il: 17 lug 2010, 18:42
Località: le 4 del mattino

0
voti

[5] Re: PIC16F1829 problema con numeri random

Messaggioda Foto UtenteTardoFreak » 1 giu 2015, 15:06

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.
"La follia sta nel fare sempre la stessa cosa aspettandosi risultati diversi".
"Parla soltanto quando sei sicuro che quello che dirai è più bello del silenzio".
Rispondere è cortesia, ma lasciare l'ultima parola ai cretini è arte.
Avatar utente
Foto UtenteTardoFreak
73,8k 8 12 13
-EY Legend-
-EY Legend-
 
Messaggi: 15754
Iscritto il: 16 dic 2009, 11:10
Località: Torino - 3° pianeta del Sistema Solare

0
voti

[6] Re: PIC16F1829 problema con numeri random

Messaggioda Foto UtenteNick01 » 1 giu 2015, 15:22

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
Avatar utente
Foto UtenteNick01
15 4
 
Messaggi: 31
Iscritto il: 29 mag 2015, 16:13

0
voti

[7] Re: PIC16F1829 problema con numeri random

Messaggioda Foto UtenteNick01 » 1 giu 2015, 20:37

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.
Avatar utente
Foto UtenteNick01
15 4
 
Messaggi: 31
Iscritto il: 29 mag 2015, 16:13

0
voti

[8] Re: PIC16F1829 problema con numeri random

Messaggioda Foto UtenteWALTERmwp » 1 giu 2015, 23:08

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
W - U.H.F.
Avatar utente
Foto UtenteWALTERmwp
29,5k 4 8 13
G.Master EY
G.Master EY
 
Messaggi: 8742
Iscritto il: 17 lug 2010, 18:42
Località: le 4 del mattino

0
voti

[9] Re: PIC16F1829 problema con numeri random

Messaggioda Foto UtenteNick01 » 2 giu 2015, 10:19

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);
    }
}
Avatar utente
Foto UtenteNick01
15 4
 
Messaggi: 31
Iscritto il: 29 mag 2015, 16:13

0
voti

[10] Re: PIC16F1829 problema con numeri random

Messaggioda Foto UtenteWALTERmwp » 2 giu 2015, 14:49

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
W - U.H.F.
Avatar utente
Foto UtenteWALTERmwp
29,5k 4 8 13
G.Master EY
G.Master EY
 
Messaggi: 8742
Iscritto il: 17 lug 2010, 18:42
Località: le 4 del mattino

Prossimo

Torna a Firmware e programmazione

Chi c’è in linea

Visitano il forum: Nessuno e 4 ospiti